//===------------- Convert.cpp - Converting gimple to LLVM IR -------------===//
//
// Copyright (C) 2005 to 2014  Chris Lattner, Duncan Sands et al.
//
// This file is part of DragonEgg.
//
// DragonEgg is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2, or (at your option) any later version.
//
// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// DragonEgg; see the file COPYING.  If not, write to the Free Software
// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
//
//===----------------------------------------------------------------------===//
// This is the code that converts GCC AST nodes into LLVM code.
//===----------------------------------------------------------------------===//

// Plugin headers
#include "dragonegg/ABI.h"
#include "dragonegg/Aliasing.h"
#include "dragonegg/ConstantConversion.h"
#include "dragonegg/Debug.h"
#include "dragonegg/TypeConversion.h"

// LLVM headers
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetSubtargetInfo.h"

// System headers
#include <gmp.h>

// GCC headers
#include "auto-host.h"
#ifndef ENABLE_BUILD_WITH_CXX
#include <cstring> // Otherwise included by system.h with C linkage.
extern "C" {
#endif
#include "config.h"
// Stop GCC declaring 'getopt' as it can clash with the system's declaration.
#undef HAVE_DECL_GETOPT
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"

#include "diagnostic.h"
#include "except.h"
#include "flags.h"
#if (GCC_MINOR > 6)
#include "gimple-pretty-print.h"
#endif
#include "langhooks.h"
#include "output.h"
#include "params.h"
#include "rtl.h"
#include "target.h" // For targetm.
#include "tm_p.h"
#include "toplev.h"
#include "tree-flow.h"
#include "tree-pass.h"

using namespace llvm;

#if (GCC_MINOR < 6)
extern enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
#else
// TODO: Submit a GCC patch to install "regs.h" as a plugin header.
struct target_regs {
  unsigned char x_hard_regno_nregs[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
  enum machine_mode x_reg_raw_mode[FIRST_PSEUDO_REGISTER];
};

extern struct target_regs default_target_regs;

#define reg_raw_mode (default_target_regs.x_reg_raw_mode)
#endif

#if (GCC_MINOR == 6)
extern void debug_gimple_stmt(union gimple_statement_d *);
#endif

#ifndef ENABLE_BUILD_WITH_CXX
} // extern "C"
#endif

// Trees header.
#include "dragonegg/Trees.h"

static LLVMContext &Context = getGlobalContext();

#define DEBUG_TYPE "dragonegg"
STATISTIC(NumBasicBlocks, "Number of basic blocks converted");
STATISTIC(NumStatements, "Number of gimple statements converted");

/// getPointerAlignment - Return the alignment in bytes of exp, a pointer valued
/// expression, or 1 if the alignment is not known.
static unsigned int getPointerAlignment(tree exp) {
  assert(isa<ACCESS_TYPE>(TREE_TYPE(exp)) && "Expected a pointer type!");
  unsigned int align =
#if (GCC_MINOR < 7)
      get_pointer_alignment(exp, BIGGEST_ALIGNMENT);
#else
  get_pointer_alignment(exp);
#endif
  return align >= 8 ? align / 8 : 1;
}

/// getSSAPlaceholder - A fake value associated with an SSA name when the name
/// is used before being defined (this can occur because basic blocks are not
/// output in dominator order).  Replaced with the correct value when the SSA
/// name's definition is encountered.
static Value *GetSSAPlaceholder(Type *Ty) {
  // Cannot use a constant, since there is no way to distinguish a fake value
  // from a real value.  So use an instruction with no parent.  This needs to
  // be an instruction that can return a struct type, since the SSA name might
  // be a complex number.  It could be a PHINode, except that the GCC phi node
  // conversion logic also constructs phi nodes with no parent.  A SelectInst
  // would work, but a LoadInst seemed neater.
  return new LoadInst(UndefValue::get(Ty->getPointerTo()), NULL);
}

/// isSSAPlaceholder - Whether this is a fake value being used as a placeholder
/// for the definition of an SSA name.
static bool isSSAPlaceholder(Value *V) {
  LoadInst *LI = llvm::dyn_cast<LoadInst>(V);
  return LI && !LI->getParent();
}

/// NameValue - Try to name the given value after the given GCC tree node.  If
/// the GCC tree node has no sensible name then it does nothing.  If the value
/// already has a name then it is not changed.
static void NameValue(Value *V, tree t) {
  if (!V->hasName()) {
    const std::string &Name = getDescriptiveName(t);
    if (!Name.empty())
      V->setName(Name);
  }
}

/// SelectFPName - Helper for choosing a name depending on whether a floating
/// point type is float, double or long double.  Returns an empty string for
/// other types, such as the x86 128 bit floating point type.
static StringRef SelectFPName(tree type, StringRef FloatName,
                              StringRef DoubleName, StringRef LongDoubleName) {
  assert(isa<REAL_TYPE>(type) && "Expected a floating point type!");
  if (TYPE_MODE(type) == TYPE_MODE(float_type_node))
    return FloatName;
  if (TYPE_MODE(type) == TYPE_MODE(double_type_node))
    return DoubleName;
  if (TYPE_MODE(type) == TYPE_MODE(long_double_type_node))
    return LongDoubleName;
  return StringRef();
}

/// DisplaceLocationByUnits - Move a memory location by a fixed number of units.
/// This uses an "inbounds" getelementptr, so the displacement should remain
/// inside the original object.
MemRef
DisplaceLocationByUnits(MemRef Loc, int32_t Offset, LLVMBuilder &Builder) {
  // Convert to a byte pointer and displace by the offset.
  unsigned AddrSpace = Loc.Ptr->getType()->getPointerAddressSpace();
  Type *UnitPtrTy = GetUnitPointerType(Context, AddrSpace);
  Value *Ptr = Builder.CreateBitCast(Loc.Ptr, UnitPtrTy);
  Ptr = Builder.CreateConstInBoundsGEP1_32(Ptr, Offset,
                                           flag_verbose_asm ? "dsplc" : "");
  Ptr = Builder.CreateBitCast(Ptr, Loc.Ptr->getType());
  uint32_t Align = MinAlign(Loc.getAlignment(), Offset);
  return MemRef(Ptr, Align, Loc.Volatile);
}

/// LoadFromLocation - Load a value of the given type from a memory location.
static LoadInst *
LoadFromLocation(MemRef Loc, Type *Ty, MDNode *AliasTag, LLVMBuilder &Builder) {
  unsigned AddrSpace = Loc.Ptr->getType()->getPointerAddressSpace();
  Value *Ptr = Builder.CreateBitCast(Loc.Ptr, Ty->getPointerTo(AddrSpace));
  LoadInst *LI =
      Builder.CreateAlignedLoad(Ptr, Loc.getAlignment(), Loc.Volatile);
  if (AliasTag)
    LI->setMetadata(LLVMContext::MD_tbaa, AliasTag);
  return LI;
}

/// StoreToLocation - Store a value to the given memory location.
static StoreInst *
StoreToLocation(Value *V, MemRef Loc, MDNode *AliasTag, LLVMBuilder &Builder) {
  Type *Ty = V->getType();
  unsigned AddrSpace = Loc.Ptr->getType()->getPointerAddressSpace();
  Value *Ptr = Builder.CreateBitCast(Loc.Ptr, Ty->getPointerTo(AddrSpace));
  StoreInst *SI =
      Builder.CreateAlignedStore(V, Ptr, Loc.getAlignment(), Loc.Volatile);
  if (AliasTag)
    SI->setMetadata(LLVMContext::MD_tbaa, AliasTag);
  return SI;
}

/// Mem2Reg - Convert a value of in-memory type (that given by ConvertType)
/// to in-register type (that given by getRegType).  TODO: Eliminate these
/// methods: "memory" values should never be held in registers.  Currently
/// this is mainly used for marshalling function parameters and return values,
/// but that should be completely independent of the reg vs mem value logic.
static Value *Mem2Reg(Value *V, tree type, LLVMBuilder &Builder) {
  Type *MemTy = V->getType();
  Type *RegTy = getRegType(type);
  assert(MemTy == ConvertType(type) && "Not of memory type!");

  if (MemTy == RegTy)
    return V;

  if (RegTy->isIntegerTy()) {
    assert(MemTy->isIntegerTy() && "Type mismatch!");
    return Builder.CreateIntCast(V, RegTy, /*isSigned*/ !TYPE_UNSIGNED(type));
  }

  if (RegTy->isPointerTy()) {
    assert(MemTy->isPointerTy() && "Type mismatch!");
    return Builder.CreateBitCast(V, RegTy);
  }

  if (RegTy->isStructTy()) {
    assert(isa<COMPLEX_TYPE>(type) && "Expected a complex type!");
    assert(MemTy->isStructTy() && "Type mismatch!");
    Value *RealPart = Builder.CreateExtractValue(V, 0);
    Value *ImagPart = Builder.CreateExtractValue(V, 1);
    RealPart = Mem2Reg(RealPart, TREE_TYPE(type), Builder);
    ImagPart = Mem2Reg(ImagPart, TREE_TYPE(type), Builder);
    V = UndefValue::get(RegTy);
    V = Builder.CreateInsertValue(V, RealPart, 0);
    V = Builder.CreateInsertValue(V, ImagPart, 1);
    return V;
  }

  if (RegTy->isVectorTy()) {
    assert(isa<VECTOR_TYPE>(type) && "Expected a vector type!");
    assert(MemTy->isVectorTy() && "Type mismatch!");
    Value *Res = UndefValue::get(RegTy);
    unsigned NumElts = (unsigned) TYPE_VECTOR_SUBPARTS(type);
    for (unsigned i = 0; i != NumElts; ++i) {
      Value *Idx = Builder.getInt32(i);
      Value *Val = Builder.CreateExtractElement(V, Idx);
      Val = Mem2Reg(Val, TREE_TYPE(type), Builder);
      Res = Builder.CreateInsertElement(Res, Val, Idx);
    }
    return Res;
  }

  debug_tree(type);
  llvm_unreachable("Don't know how to turn this into a register!");
}

/// Reg2Mem - Convert a value of in-register type (that given by getRegType)
/// to in-memory type (that given by ConvertType).  TODO: Eliminate this
/// method: "memory" values should never be held in registers.  Currently
/// this is mainly used for marshalling function parameters and return values,
/// but that should be completely independent of the reg vs mem value logic.
static Value *Reg2Mem(Value *V, tree type, LLVMBuilder &Builder) {
  Type *RegTy = V->getType();
  Type *MemTy = ConvertType(type);
  assert(RegTy == getRegType(type) && "Not of register type!");

  if (RegTy == MemTy)
    return V;

  if (MemTy->isIntegerTy()) {
    assert(RegTy->isIntegerTy() && "Type mismatch!");
    return Builder.CreateIntCast(V, MemTy, /*isSigned*/ !TYPE_UNSIGNED(type));
  }

  if (MemTy->isPointerTy()) {
    assert(RegTy->isPointerTy() && "Type mismatch!");
    return Builder.CreateBitCast(V, MemTy);
  }

  if (MemTy->isStructTy()) {
    assert(isa<COMPLEX_TYPE>(type) && "Expected a complex type!");
    assert(RegTy->isStructTy() && "Type mismatch!");
    Value *RealPart = Builder.CreateExtractValue(V, 0);
    Value *ImagPart = Builder.CreateExtractValue(V, 1);
    RealPart = Reg2Mem(RealPart, TREE_TYPE(type), Builder);
    ImagPart = Reg2Mem(ImagPart, TREE_TYPE(type), Builder);
    Value *Z = UndefValue::get(MemTy);
    Z = Builder.CreateInsertValue(Z, RealPart, 0);
    Z = Builder.CreateInsertValue(Z, ImagPart, 1);
    return Z;
  }

  if (MemTy->isVectorTy()) {
    assert(isa<VECTOR_TYPE>(type) && "Expected a vector type!");
    assert(RegTy->isVectorTy() && "Type mismatch!");
    Value *Res = UndefValue::get(MemTy);
    unsigned NumElts = (unsigned) TYPE_VECTOR_SUBPARTS(type);
    for (unsigned i = 0; i != NumElts; ++i) {
      Value *Idx = Builder.getInt32(i);
      Value *Val = Builder.CreateExtractElement(V, Idx);
      Val = Reg2Mem(Val, TREE_TYPE(type), Builder);
      Res = Builder.CreateInsertElement(Res, Val, Idx);
    }
    return Res;
  }

  debug_tree(type);
  llvm_unreachable("Don't know how to turn this into memory!");
}

/// describeTypeRange - Return metadata describing the set of possible values
/// that an in-memory variable of the given GCC type can take on.
static MDNode *describeTypeRange(tree type) {
  if (!isa<INTEGRAL_TYPE>(type))
    return 0; // Only discrete types have ranges.

  // The range of possible values is TYPE_MIN_VALUE .. TYPE_MAX_VALUE.
  tree min = TYPE_MIN_VALUE(type);
  assert(min && isa<INTEGER_CST>(min) && "Min not a constant!");
  tree max = TYPE_MAX_VALUE(type);
  assert(max && isa<INTEGER_CST>(max) && "Max not a constant!");

  unsigned BitWidth = GET_MODE_BITSIZE(TYPE_MODE(type));

  APInt Lo = getAPIntValue(min, BitWidth);
  APInt Hi = getAPIntValue(max, BitWidth);

  // Unlike GCC's, LLVM ranges do not include the upper end point.
  ++Hi;

  MDBuilder MDHelper(Context);
  return MDHelper.createRange(Lo, Hi);
}

/// isDirectMemoryAccessSafe - Whether directly storing/loading a value of the
/// given register type generates the correct in-memory representation for the
/// type.  Eg, if a 32 bit wide integer type has only one bit of precision then
/// the register type is i1 and the in-memory type i32.  Storing an i1 directly
/// to memory would not properly set up all 32 in-memory bits, thus this method
/// would return false.
static bool isDirectMemoryAccessSafe(Type *RegTy, tree type) {
  assert(RegTy == getRegType(type) && "Wrong register type!");

  switch (TREE_CODE(type)) {
  default:
    debug_tree(type);
    llvm_unreachable("Unknown register type!");

  case BOOLEAN_TYPE:
  case ENUMERAL_TYPE:
  case INTEGER_TYPE:
    assert(RegTy->isIntegerTy() && "Expected an integer type!");
    return RegTy->getIntegerBitWidth() == GET_MODE_BITSIZE(TYPE_MODE(type));

  case COMPLEX_TYPE:
  case VECTOR_TYPE: {
    assert((!isa<COMPLEX_TYPE>(type) || RegTy->isStructTy()) &&
           "Expected a struct type!");
    assert((!isa<VECTOR_TYPE>(type) || RegTy->isVectorTy()) &&
           "Expected a vector type!");
    tree elt_type = main_type(type);
    Type *EltRegTy = getRegType(elt_type);
    // Check that fields are safe to access directly.
    if (!isDirectMemoryAccessSafe(EltRegTy, elt_type))
      return false;
    // Check that the field positions agree with GCC.
    unsigned StrideBits = GET_MODE_BITSIZE(TYPE_MODE(elt_type));
    return getDataLayout().getTypeAllocSizeInBits(EltRegTy) == StrideBits;
  }

  case OFFSET_TYPE:
    assert(RegTy->isIntegerTy() && "Expected an integer type!");
    return true;

#if (GCC_MINOR > 5)
  case NULLPTR_TYPE:
#endif
  case POINTER_TYPE:
  case REFERENCE_TYPE:
    assert(RegTy->isPointerTy() && "Expected a pointer type!");
    return true;

  case REAL_TYPE:
    assert(RegTy->isFloatingPointTy() && "Expected a floating point type!");
    // NOTE: This might be wrong for floats with precision less than their alloc
    // size on big-endian machines.
    return true;
  }
}

/// LoadRegisterFromMemory - Loads a value of the given scalar GCC type from
/// the memory location pointed to by Loc.  Takes care of adjusting for any
/// differences between in-memory and in-register types (the returned value
/// is of in-register type, as returned by getRegType).
static Value *LoadRegisterFromMemory(MemRef Loc, tree type, MDNode *AliasTag,
                                     LLVMBuilder &Builder) {
  // NOTE: Needs to be kept in sync with getRegType.
  Type *RegTy = getRegType(type);

  // If loading the register type directly out of memory gives the right result,
  // then just do that.
  if (isDirectMemoryAccessSafe(RegTy, type)) {
    LoadInst *LI = LoadFromLocation(Loc, RegTy, AliasTag, Builder);
    MDNode *Range = describeTypeRange(type);
    if (Range)
      LI->setMetadata(LLVMContext::MD_range, Range);
    return LI;
  }

  // There is a discrepancy between the in-register type and the in-memory type.
  switch (TREE_CODE(type)) {
  default:
    debug_tree(type);
    llvm_unreachable("Unexpected type mismatch!");

  case BOOLEAN_TYPE:
  case ENUMERAL_TYPE:
  case INTEGER_TYPE: {
    // For integral types, load an integer with size equal to the mode size,
    // then truncate down to the precision.  For example, when extracting a bool
    // this probably first loads out an i8 or i32 which is then truncated to i1.
    // This roundabout approach means we get the right result on both little and
    // big endian machines.
    unsigned Size = GET_MODE_BITSIZE(TYPE_MODE(type));
    Type *MemTy = IntegerType::get(Context, Size);
    LoadInst *LI = LoadFromLocation(Loc, MemTy, AliasTag, Builder);
    MDNode *Range = describeTypeRange(type);
    if (Range)
      LI->setMetadata(LLVMContext::MD_range, Range);
    return Builder.CreateTruncOrBitCast(LI, RegTy);
  }

  case COMPLEX_TYPE: {
    // Load the complex number component by component.
    tree elt_type = main_type(type);
    unsigned Stride = GET_MODE_SIZE(TYPE_MODE(elt_type));
    Value *RealPart = LoadRegisterFromMemory(Loc, elt_type, AliasTag, Builder);
    Loc = DisplaceLocationByUnits(Loc, Stride, Builder);
    Value *ImagPart = LoadRegisterFromMemory(Loc, elt_type, AliasTag, Builder);
    Value *Res = UndefValue::get(RegTy);
    Res = Builder.CreateInsertValue(Res, RealPart, 0);
    Res = Builder.CreateInsertValue(Res, ImagPart, 1);
    return Res;
  }

  case VECTOR_TYPE: {
    tree elt_type = main_type(type);
    Type *EltRegTy = getRegType(elt_type);
    unsigned NumElts = TYPE_VECTOR_SUBPARTS(type);
    unsigned Size = GET_MODE_BITSIZE(TYPE_MODE(elt_type));
    // If, say, the register type is a vector of i1 but memory is laid out as a
    // vector of i32 then load an i32 vector out and truncate to a vector of i1.
    if (EltRegTy->isIntegerTy() && EltRegTy->getIntegerBitWidth() != Size) {
      // See if changing the element type to an integer with size equal to the
      // mode size gives a vector type that corresponds to the in-memory layout.
      Type *MemTy = IntegerType::get(Context, Size);
      if (getDataLayout().getTypeAllocSizeInBits(MemTy) == Size) {
        // It does!  Load out the memory as a vector of that type then truncate
        // to the register size.
        Type *MemVecTy = VectorType::get(MemTy, NumElts);
        LoadInst *LI = LoadFromLocation(Loc, MemVecTy, AliasTag, Builder);
        return Builder.CreateTruncOrBitCast(LI, RegTy);
      }
    }
    // Otherwise, load the vector component by component.
    Value *Res = UndefValue::get(RegTy);
    unsigned Stride = GET_MODE_SIZE(TYPE_MODE(elt_type));
    for (unsigned i = 0; i != NumElts; ++i) {
      Value *Idx = Builder.getInt32(i);
      Value *Elt = LoadRegisterFromMemory(Loc, elt_type, AliasTag, Builder);
      Res = Builder.CreateInsertElement(Res, Elt, Idx);
      if (i + 1 != NumElts)
        Loc = DisplaceLocationByUnits(Loc, Stride, Builder);
    }
    return Res;
  }
  }
}

/// StoreRegisterToMemory - Stores the given value to the memory pointed to by
/// Loc.  Takes care of adjusting for any differences between the value's type
/// (which is the in-register type given by getRegType) and the in-memory type.
static void StoreRegisterToMemory(Value *V, MemRef Loc, tree type,
                                  MDNode *AliasTag, LLVMBuilder &Builder) {
  // NOTE: Needs to be kept in sync with getRegType.
  assert(V->getType() == getRegType(type) && "Not of register type!");

  // If storing the register directly to memory gives the right result, then
  // just do that.
  if (isDirectMemoryAccessSafe(V->getType(), type)) {
    StoreToLocation(V, Loc, AliasTag, Builder);
    return;
  }

  // There is a discrepancy between the in-register type and the in-memory type.
  switch (TREE_CODE(type)) {
  default:
    debug_tree(type);
    llvm_unreachable("Unexpected type mismatch!");

  case BOOLEAN_TYPE:
  case ENUMERAL_TYPE:
  case INTEGER_TYPE: {
    // For integral types extend to an integer with size equal to the mode size.
    // For example, when inserting a bool this probably extends it to an i8 or
    // to an i32.  This approach means we get the right result on both little
    // and big endian machines.
    unsigned Size = GET_MODE_BITSIZE(TYPE_MODE(type));
    Type *MemTy = IntegerType::get(Context, Size);
    V = Builder.CreateIntCast(V, MemTy, /*isSigned*/ !TYPE_UNSIGNED(type));
    StoreToLocation(V, Loc, AliasTag, Builder);
    break;
  }

  case COMPLEX_TYPE: {
    // Store the complex number component by component.
    tree elt_type = main_type(type);
    unsigned Stride = GET_MODE_SIZE(TYPE_MODE(elt_type));
    Value *RealPart = Builder.CreateExtractValue(V, 0);
    Value *ImagPart = Builder.CreateExtractValue(V, 1);
    StoreRegisterToMemory(RealPart, Loc, elt_type, AliasTag, Builder);
    Loc = DisplaceLocationByUnits(Loc, Stride, Builder);
    StoreRegisterToMemory(ImagPart, Loc, elt_type, AliasTag, Builder);
    break;
  }

  case VECTOR_TYPE: {
    tree elt_type = main_type(type);
    Type *EltRegTy = getRegType(elt_type);
    unsigned NumElts = TYPE_VECTOR_SUBPARTS(type);
    unsigned Size = GET_MODE_BITSIZE(TYPE_MODE(elt_type));
    // If, say, the register type is a vector of i1 but memory is laid out as a
    // vector of i32 then extend the i1 vector to an i32 vector and store that.
    if (EltRegTy->isIntegerTy() && EltRegTy->getIntegerBitWidth() != Size) {
      // See if changing the element type to an integer with size equal to the
      // mode size gives a vector type that corresponds to the in-memory layout.
      Type *MemTy = IntegerType::get(Context, Size);
      if (getDataLayout().getTypeAllocSizeInBits(MemTy) == Size) {
        // It does!  Extend the register value to a vector of that type then
        // store it to memory.
        Type *MemVecTy = VectorType::get(MemTy, NumElts);
        V = Builder.CreateIntCast(V, MemVecTy,
                                  /*isSigned*/ !TYPE_UNSIGNED(elt_type));
        StoreToLocation(V, Loc, AliasTag, Builder);
        break;
      }
    }
    // Otherwise, store the vector component by component.
    unsigned Stride = GET_MODE_SIZE(TYPE_MODE(elt_type));
    for (unsigned i = 0; i != NumElts; ++i) {
      Value *Idx = Builder.getInt32(i);
      Value *Elt = Builder.CreateExtractElement(V, Idx);
      StoreRegisterToMemory(Elt, Loc, elt_type, AliasTag, Builder);
      if (i + 1 != NumElts)
        Loc = DisplaceLocationByUnits(Loc, Stride, Builder);
    }
    break;
  }
  }
}

//===----------------------------------------------------------------------===//
//                         ... High-Level Methods ...
//===----------------------------------------------------------------------===//

/// TheTreeToLLVM - Keep track of the current function being compiled.
TreeToLLVM *TheTreeToLLVM = 0;

const DataLayout &getDataLayout() {
  return *TheTarget->getSubtargetImpl()->getDataLayout();
}

/// EmitDebugInfo - Return true if debug info is to be emitted for current
/// function.
bool TreeToLLVM::EmitDebugInfo() {
  if (TheDebugInfo && !DECL_IGNORED_P(getFUNCTION_DECL()))
    return true;
  return false;
}

TreeToLLVM::TreeToLLVM(tree fndecl)
    : DL(getDataLayout()), Builder(Context, *TheFolder) {
  FnDecl = fndecl;
  AllocaInsertionPoint = 0;
  Fn = 0;
  ReturnBB = 0;
  ReturnOffset = 0;

  if (EmitDebugInfo()) {
    expanded_location Location = expand_location(DECL_SOURCE_LOCATION(fndecl));

    if (Location.file) {
      TheDebugInfo->setLocationFile(Location.file);
      TheDebugInfo->setLocationLine(Location.line);
    } else {
      TheDebugInfo->setLocationFile("");
      TheDebugInfo->setLocationLine(0);
    }
  }

  assert(TheTreeToLLVM == 0 && "Reentering function creation?");
  TheTreeToLLVM = this;
}

TreeToLLVM::~TreeToLLVM() { TheTreeToLLVM = 0; }

//===----------------------------------------------------------------------===//
//                         ... Local declarations ...
//===----------------------------------------------------------------------===//

/// isLocalDecl - Whether this declaration is local to the current function.
static bool isLocalDecl(tree decl) {
  if (isa<CONST_DECL>(decl))
    return false;
  assert(HAS_RTL_P(decl) && "Expected a declaration with RTL!");
  return
      // GCC bug workaround: RESULT_DECL may not have DECL_CONTEXT set in thunks.
      (!DECL_CONTEXT(decl) && isa<RESULT_DECL>(decl)) ||
                                   // Usual case.
      (DECL_CONTEXT(decl) == current_function_decl &&
       !DECL_EXTERNAL(decl) &&     // External variables are not local.
       !TREE_STATIC(decl) &&       // Static variables not considered local.
       !isa<FUNCTION_DECL>(decl)); // Nested functions not considered local.
}

/// set_decl_local - Remember the LLVM value for a GCC declaration.
Value *TreeToLLVM::set_decl_local(tree decl, Value *V) {
  if (!isLocalDecl(decl))
    return SET_DECL_LLVM(decl, V);
  if (V != NULL)
    return LocalDecls[decl] = V;
  LocalDecls.erase(decl);
  return NULL;
}

/// get_decl_local - Retrieve the LLVM value for a GCC declaration, or NULL.
Value *TreeToLLVM::get_decl_local(tree decl) {
  if (!isLocalDecl(decl))
    return get_decl_llvm(decl);
  DenseMap<tree, AssertingVH<Value> >::iterator I = LocalDecls.find(decl);
  if (I != LocalDecls.end())
    return I->second;
  return NULL;
}

/// make_decl_local - Return the LLVM value for a GCC declaration if it exists.
/// Otherwise creates and returns an appropriate value.
Value *TreeToLLVM::make_decl_local(tree decl) {
  if (!isLocalDecl(decl))
    return make_decl_llvm(decl);

  DenseMap<tree, AssertingVH<Value> >::iterator I = LocalDecls.find(decl);
  if (I != LocalDecls.end())
    return I->second;

  switch (TREE_CODE(decl)) {
  default:
    debug_tree(decl);
    llvm_unreachable("Unhandled local declaration!");

  case RESULT_DECL:
  case VAR_DECL:
    EmitAutomaticVariableDecl(decl);
    I = LocalDecls.find(decl);
    assert(I != LocalDecls.end() && "Not a local variable?");
    return I->second;
  }
}

/// make_definition_local - Ensure that the body or initial value of the given
/// GCC declaration will be output, and return a declaration for it.
Value *TreeToLLVM::make_definition_local(tree decl) {
  if (!isLocalDecl(decl))
    return make_definition_llvm(decl);
  return make_decl_local(decl);
}

/// llvm_store_scalar_argument - Store scalar argument ARGVAL of type
/// LLVMTY at location LOC.
static void llvm_store_scalar_argument(Value *Loc, Value *ArgVal,
                                       llvm::Type *LLVMTy, unsigned RealSize,
                                       LLVMBuilder &Builder) {
  if (RealSize) {
    // Not clear what this is supposed to do on big endian machines...
    assert(!BYTES_BIG_ENDIAN && "Unsupported case - please report");
    // Do byte wise store because actual argument type does not match LLVMTy.
    assert(ArgVal->getType()->isIntegerTy() && "Expected an integer value!");
    Type *StoreType = IntegerType::get(Context, RealSize * 8);
    Loc = Builder.CreateBitCast(Loc, StoreType->getPointerTo());
    if (ArgVal->getType()->getPrimitiveSizeInBits() >=
        StoreType->getPrimitiveSizeInBits())
      ArgVal = Builder.CreateTrunc(ArgVal, StoreType);
    else
      ArgVal = Builder.CreateZExt(ArgVal, StoreType);
    Builder.CreateStore(ArgVal, Loc);
  } else {
    // This cast only involves pointers, therefore BitCast.
    Loc = Builder.CreateBitCast(Loc, LLVMTy->getPointerTo());
    // FIXME: Pass down the alignment so we can do better than using 1 here.
    Builder.CreateAlignedStore(ArgVal, Loc, 1);
  }
}

#ifndef LLVM_STORE_SCALAR_ARGUMENT
#define LLVM_STORE_SCALAR_ARGUMENT(LOC, ARG, TYPE, SIZE, BUILDER)              \
  llvm_store_scalar_argument((LOC), (ARG), (TYPE), (SIZE), (BUILDER))
#endif

// This is true for types whose alignment when passed on the stack is less
// than the alignment of the type.
#define LLVM_BYVAL_ALIGNMENT_TOO_SMALL(T)                                      \
  (LLVM_BYVAL_ALIGNMENT(T) && LLVM_BYVAL_ALIGNMENT(T) < TYPE_ALIGN_UNIT(T))

namespace {
/// FunctionPrologArgumentConversion - This helper class is driven by the ABI
/// definition for this target to figure out how to retrieve arguments from
/// the stack/regs coming into a function and store them into an appropriate
/// alloca for the argument.
struct FunctionPrologArgumentConversion : public DefaultABIClient {
  tree FunctionDecl;
  Function::arg_iterator &AI;
  LLVMBuilder Builder;
  std::vector<Value *> LocStack;
  std::vector<std::string> NameStack;
  CallingConv::ID &CallingConv;
  unsigned Offset;
  bool isShadowRet;
  FunctionPrologArgumentConversion(tree FnDecl, Function::arg_iterator &ai,
                                   const LLVMBuilder &B, CallingConv::ID &CC)
      : FunctionDecl(FnDecl), AI(ai), Builder(B), CallingConv(CC), Offset(0),
        isShadowRet(false) {}

  /// getCallingConv - This provides the desired CallingConv for the function.
  CallingConv::ID getCallingConv(void) { return CallingConv; }

  void HandlePad(llvm::Type */*LLVMTy*/) { ++AI; }

  bool isShadowReturn() const { return isShadowRet; }
  void setName(const std::string &Name) { NameStack.push_back(Name); }
  void setLocation(Value *Loc) { LocStack.push_back(Loc); }
  void clear() {
    assert(NameStack.size() == 1 && LocStack.size() == 1 && "Imbalance!");
    NameStack.clear();
    LocStack.clear();
  }

  void HandleAggregateShadowResult(PointerType */*PtrArgTy*/, bool /*RetPtr*/) {
    // If the function returns a structure by value, we transform the function
    // to take a pointer to the result as the first argument of the function
    // instead.
    assert(AI != Builder.GetInsertBlock()->getParent()->arg_end() &&
           "No explicit return value?");
    AI->setName("agg.result");

    isShadowRet = true;
    tree ResultDecl = DECL_RESULT(FunctionDecl);
    tree RetTy = TREE_TYPE(TREE_TYPE(FunctionDecl));
    if (TREE_CODE(RetTy) == TREE_CODE(TREE_TYPE(ResultDecl))) {
      TheTreeToLLVM->set_decl_local(ResultDecl, AI);
      ++AI;
      return;
    }

    // Otherwise, this must be something returned with NRVO.
    assert(isa<REFERENCE_TYPE>(TREE_TYPE(ResultDecl)) &&
           "Not type match and not passing by reference?");
    // Create an alloca for the ResultDecl.
    Value *Tmp = TheTreeToLLVM->CreateTemporary(AI->getType());
    Builder.CreateStore(AI, Tmp);

    TheTreeToLLVM->set_decl_local(ResultDecl, Tmp);
    if (TheDebugInfo && !DECL_IGNORED_P(FunctionDecl)) {
      TheDebugInfo->EmitDeclare(ResultDecl, dwarf::DW_TAG_auto_variable,
                                "agg.result", RetTy, Tmp, Builder);
    }
    ++AI;
  }

  void HandleScalarShadowResult(PointerType */*PtrArgTy*/, bool /*RetPtr*/) {
    assert(AI != Builder.GetInsertBlock()->getParent()->arg_end() &&
           "No explicit return value?");
    AI->setName("scalar.result");
    isShadowRet = true;
    TheTreeToLLVM->set_decl_local(DECL_RESULT(FunctionDecl), AI);
    ++AI;
  }

  void HandleScalarArgument(llvm::Type *LLVMTy, tree /*type*/,
                            unsigned RealSize = 0) {
    Value *ArgVal = AI;
    if (ArgVal->getType() != LLVMTy) {
      if (ArgVal->getType()->isPointerTy() && LLVMTy->isPointerTy()) {
        // If this is GCC being sloppy about pointer types, insert a bitcast.
        // See PR1083 for an example.
        ArgVal = Builder.CreateBitCast(ArgVal, LLVMTy);
      } else if (ArgVal->getType()->isDoubleTy()) {
        // If this is a K&R float parameter, it got promoted to double. Insert
        // the truncation to float now.
        ArgVal = Builder.CreateFPTrunc(ArgVal, LLVMTy, NameStack.back());
      } else {
        // If this is just a mismatch between integer types, this is due
        // to K&R prototypes, where the forward proto defines the arg as int
        // and the actual impls is a short or char.
        assert(ArgVal->getType()->isIntegerTy(32) && LLVMTy->isIntegerTy() &&
               "Lowerings don't match?");
        ArgVal = Builder.CreateTrunc(ArgVal, LLVMTy, NameStack.back());
      }
    }
    assert(!LocStack.empty());
    Value *Loc = LocStack.back();
    LLVM_STORE_SCALAR_ARGUMENT(Loc, ArgVal, LLVMTy, RealSize, Builder);
    AI->setName(NameStack.back());
    ++AI;
  }

  void HandleByValArgument(llvm::Type */*LLVMTy*/, tree type) {
    if (LLVM_BYVAL_ALIGNMENT_TOO_SMALL(type)) {
      // Incoming object on stack is insufficiently aligned for the type.
      // Make a correctly aligned copy.
      assert(!LocStack.empty());
      Value *Loc = LocStack.back();
      // We cannot use field-by-field copy here; x86 long double is 16
      // bytes, but only 10 are copied.  If the object is really a union
      // we might need the other bytes.  We must also be careful to use
      // the smaller alignment.
      Type *SBP = Type::getInt8PtrTy(Context);
      Type *IntPtr = getDataLayout().getIntPtrType(Context, 0);
      Value *Ops[5] = {
        Builder.CreateCast(Instruction::BitCast, Loc, SBP),
        Builder.CreateCast(Instruction::BitCast, AI, SBP),
        ConstantInt::get(IntPtr, TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type))),
        Builder.getInt32(LLVM_BYVAL_ALIGNMENT(type)), Builder.getFalse()
      };
      Type *ArgTypes[3] = { SBP, SBP, IntPtr };
      Builder.CreateCall(
          Intrinsic::getDeclaration(TheModule, Intrinsic::memcpy, ArgTypes),
          Ops);

      AI->setName(NameStack.back());
    }
    ++AI;
  }

  void HandleFCAArgument(llvm::Type */*LLVMTy*/, tree /*type*/) {
    // Store the FCA argument into alloca.
    assert(!LocStack.empty());
    Value *Loc = LocStack.back();
    Builder.CreateStore(AI, Loc);
    AI->setName(NameStack.back());
    ++AI;
  }

  void HandleAggregateResultAsScalar(Type */*ScalarTy*/, unsigned Off = 0) {
    this->Offset = Off;
  }

  void EnterField(unsigned FieldNo, llvm::Type *StructTy) {
    NameStack.push_back(NameStack.back() + "." + utostr(FieldNo));

    Value *Loc = LocStack.back();
    // This cast only involves pointers, therefore BitCast.
    Loc = Builder.CreateBitCast(Loc, StructTy->getPointerTo());

    Loc = Builder.CreateStructGEP(Loc, FieldNo, flag_verbose_asm ? "ntr" : "");
    LocStack.push_back(Loc);
  }
  void ExitField() {
    NameStack.pop_back();
    LocStack.pop_back();
  }
};
}

// isPassedByVal - Return true if an aggregate of the specified type will be
// passed in memory byval.
static bool isPassedByVal(tree type, Type *Ty, std::vector<Type *> &ScalarArgs,
                          bool isShadowRet, CallingConv::ID CC) {
  (void) type;
  (void) Ty;
  (void) ScalarArgs;
  (void) isShadowRet;
  (void) CC; // Not used by all ABI macros.
  if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty))
    return true;

  std::vector<Type *> Args;
  if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty, CC, Args) &&
      LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(Args, ScalarArgs, isShadowRet,
                                              CC))
    // We want to pass the whole aggregate in registers but only some of the
    // registers are available.
    return true;
  return false;
}

void TreeToLLVM::StartFunctionBody() {
  // TODO: Add support for dropping the leading '\1' in order to support
  //   unsigned bswap(unsigned) __asm__("llvm.bswap");
  // This would also require adjustments in make_decl_llvm.

  // Determine the FunctionType and calling convention for this function.
  tree static_chain = cfun->static_chain_decl;
  FunctionType *FTy;
  CallingConv::ID CallingConv;
  AttributeSet PAL;

  // If this is a K&R-style function: with a type that takes no arguments but
  // with arguments none the less, then calculate the LLVM type from the list
  // of arguments.
  if (flag_functions_from_args ||
      (TYPE_ARG_TYPES(TREE_TYPE(FnDecl)) == 0 && DECL_ARGUMENTS(FnDecl))) {
    SmallVector<tree, 8> Args;
    for (tree Arg = DECL_ARGUMENTS(FnDecl); Arg; Arg = TREE_CHAIN(Arg))
      Args.push_back(Arg);
    FTy = ConvertArgListToFnType(TREE_TYPE(FnDecl), Args, static_chain,
                                 !flag_functions_from_args, CallingConv, PAL);
  } else {
    // Otherwise, just get the type from the function itself.
    FTy = ConvertFunctionType(TREE_TYPE(FnDecl), FnDecl, static_chain,
                              CallingConv, PAL);
  }

  // If we've already seen this function and created a prototype, and if the
  // proto has the right LLVM type, just use it.
  if (DECL_LOCAL_SET_P(FnDecl) &&
      cast<PointerType>(DECL_LOCAL(FnDecl)->getType())->getElementType() ==
      FTy) {
    Fn = cast<Function>(DECL_LOCAL(FnDecl));
    assert(Fn->getCallingConv() == CallingConv &&
           "Calling convention disagreement between prototype and impl!");
    // The visibility can be changed from the last time we've seen this
    // function. Set to current.
    handleVisibility(FnDecl, Fn);
  } else {
    std::string Name = getAssemblerName(FnDecl);
    Function *FnEntry = TheModule->getFunction(Name);
    if (FnEntry) {
      assert(FnEntry->getName() == Name && "Same entry, different name?");
      assert((FnEntry->isDeclaration() ||
              FnEntry->getLinkage() == Function::AvailableExternallyLinkage) &&
             "Multiple fns with same name and neither are external!");
      FnEntry->setName(""); // Clear name to avoid conflicts.
      assert(FnEntry->getCallingConv() == CallingConv &&
             "Calling convention disagreement between prototype and impl!");
    }

    // Otherwise, either it exists with the wrong type or it doesn't exist.  In
    // either case create a new function.
    Fn = Function::Create(FTy, Function::ExternalLinkage, Name, TheModule);
    assert(Fn->getName() == Name && "Preexisting fn with the same name!");
    Fn->setCallingConv(CallingConv);
    Fn->setAttributes(PAL);

    // If a previous proto existed with the wrong type, replace any uses of it
    // with the actual function and delete the proto.
    if (FnEntry) {
      FnEntry->replaceAllUsesWith(
          TheFolder->CreateBitCast(Fn, FnEntry->getType()));
      changeLLVMConstant(FnEntry, Fn);
      FnEntry->eraseFromParent();
    }
    SET_DECL_LOCAL(FnDecl, Fn);
  }

  // The function should not already have a body.
  assert(Fn->empty() && "Function expanded multiple times!");

  // Compute the linkage that the function should get.
  if (false) { //FIXME DECL_LLVM_PRIVATE(FnDecl)) {
    Fn->setLinkage(Function::PrivateLinkage);
  } else if (!TREE_PUBLIC(FnDecl) /*|| lang_hooks.llvm_is_in_anon(subr)*/) {
    Fn->setLinkage(Function::InternalLinkage);
  } else if (DECL_COMDAT(FnDecl)) {
    Fn->setLinkage(Function::getLinkOnceLinkage(flag_odr));
  } else if (DECL_WEAK(FnDecl)) {
    // The user may have explicitly asked for weak linkage - ignore flag_odr.
    Fn->setLinkage(Function::WeakAnyLinkage);
  } else if (DECL_ONE_ONLY(FnDecl)) {
    Fn->setLinkage(Function::getWeakLinkage(flag_odr));
  } else if (DECL_EXTERNAL(FnDecl)) {
    Fn->setLinkage(Function::AvailableExternallyLinkage);
  }

#ifdef TARGET_ADJUST_LLVM_LINKAGE
  TARGET_ADJUST_LLVM_LINKAGE(Fn, FnDecl);
#endif /* TARGET_ADJUST_LLVM_LINKAGE */

  Fn->setUnnamedAddr(!TREE_ADDRESSABLE(FnDecl));

  // Handle visibility style
  handleVisibility(FnDecl, Fn);

  // Register constructors and destructors.
  if (DECL_STATIC_CONSTRUCTOR(FnDecl))
    register_ctor_dtor(Fn, DECL_INIT_PRIORITY(FnDecl), true);
  if (DECL_STATIC_DESTRUCTOR(FnDecl))
    register_ctor_dtor(Fn, DECL_FINI_PRIORITY(FnDecl), false);

  // Handle attribute "aligned".
  if (DECL_ALIGN(FnDecl) != FUNCTION_BOUNDARY)
    Fn->setAlignment(DECL_ALIGN(FnDecl) / 8);

  // Handle functions in specified sections.
  if (DECL_SECTION_NAME(FnDecl))
    Fn->setSection(TREE_STRING_POINTER(DECL_SECTION_NAME(FnDecl)));

  // Handle used Functions
  if (lookup_attribute("used", DECL_ATTRIBUTES(FnDecl)))
    AttributeUsedGlobals.insert(Fn);

  // Handle noinline Functions
  if (lookup_attribute("noinline", DECL_ATTRIBUTES(FnDecl)))
    Fn->addFnAttr(Attribute::NoInline);

  // Handle always_inline attribute
  if (lookup_attribute("always_inline", DECL_ATTRIBUTES(FnDecl)))
    Fn->addFnAttr(Attribute::AlwaysInline);

  // Pass inline keyword to optimizer.
  if (DECL_DECLARED_INLINE_P(FnDecl))
    Fn->addFnAttr(Attribute::InlineHint);

  if (optimize_size)
    Fn->addFnAttr(Attribute::OptimizeForSize);

  // Handle stack smashing protection.
  if (flag_stack_protect == 1)
    Fn->addFnAttr(Attribute::StackProtect);
  else if (flag_stack_protect == 2)
    Fn->addFnAttr(Attribute::StackProtectReq);
  else if (flag_stack_protect == 3)
    Fn->addFnAttr(Attribute::StackProtectStrong);
  if (flag_stack_protect)
    Fn->addFnAttr("stack-protector-buffer-size",
                  utostr(PARAM_VALUE(PARAM_SSP_BUFFER_SIZE)));

  // Handle naked attribute
  if (lookup_attribute("naked", DECL_ATTRIBUTES(FnDecl)))
    Fn->addFnAttr(Attribute::Naked);

  // Handle frame pointers.
  if (flag_omit_frame_pointer) {
    // Eliminate frame pointers everywhere.
    Fn->addFnAttr("no-frame-pointer-elim-non-leaf", "false");
  } else {
    // Keep frame pointers everywhere.
    Fn->addFnAttr("no-frame-pointer-elim-non-leaf", "true");
  }

#ifdef LLVM_SET_TARGET_MACHINE_ATTRIBUTES
  LLVM_SET_TARGET_MACHINE_ATTRIBUTES(Fn);
#endif

  // Handle annotate attributes
  if (DECL_ATTRIBUTES(FnDecl))
    AddAnnotateAttrsToGlobal(Fn, FnDecl);

  // Mark the function "nounwind" if not doing exception handling.
  if (!flag_exceptions)
    Fn->setDoesNotThrow();

  if (flag_unwind_tables)
    Fn->setHasUWTable();

  // Create a new basic block for the function.
  BasicBlock *EntryBlock = BasicBlock::Create(Context, "entry", Fn);
  BasicBlocks[ENTRY_BLOCK_PTR] = EntryBlock;
  Builder.SetInsertPoint(EntryBlock);

  if (EmitDebugInfo())
    TheDebugInfo->EmitFunctionStart(FnDecl, Fn);

  // Loop over all of the arguments to the function, setting Argument names and
  // creating argument alloca's for the PARM_DECLs in case their address is
  // exposed.
  Function::arg_iterator AI = Fn->arg_begin();

  // Rename and alloca'ify real arguments.
  FunctionPrologArgumentConversion Client(FnDecl, AI, Builder, CallingConv);
  DefaultABI ABIConverter(Client);

  // Handle the DECL_RESULT.
  ABIConverter.HandleReturnType(TREE_TYPE(TREE_TYPE(FnDecl)), FnDecl,
                                DECL_BUILT_IN(FnDecl));
  // Remember this for use by FinishFunctionBody.
  TheTreeToLLVM->ReturnOffset = Client.Offset;

  // Prepend the static chain (if any) to the list of arguments.
  tree Args = static_chain ? static_chain : DECL_ARGUMENTS(FnDecl);

  // Scalar arguments processed so far.
  std::vector<Type *> ScalarArgs;
  while (Args) {
    std::string Name = getDescriptiveName(Args);
    if (Name.empty())
      Name = "unnamed_arg";

    Type *ArgTy = ConvertType(TREE_TYPE(Args));
    bool isInvRef = isPassedByInvisibleReference(TREE_TYPE(Args));
    if (isInvRef ||
        (ArgTy->isVectorTy() &&
         LLVM_SHOULD_PASS_VECTOR_USING_BYVAL_ATTR(TREE_TYPE(Args)) &&
         !LLVM_BYVAL_ALIGNMENT_TOO_SMALL(TREE_TYPE(Args))) ||
        (!ArgTy->isSingleValueType() &&
         isPassedByVal(TREE_TYPE(Args), ArgTy, ScalarArgs,
                       Client.isShadowReturn(), CallingConv) &&
         !LLVM_BYVAL_ALIGNMENT_TOO_SMALL(TREE_TYPE(Args)))) {
      // If the value is passed by 'invisible reference' or 'byval reference',
      // the l-value for the argument IS the argument itself.  But for byval
      // arguments whose alignment as an argument is less than the normal
      // alignment of the type (examples are x86-32 aggregates containing long
      // double and large x86-64 vectors), we need to make the copy.
      AI->setName(Name);
      SET_DECL_LOCAL(Args, AI);
      if (!isInvRef && EmitDebugInfo())
        TheDebugInfo->EmitDeclare(Args, dwarf::DW_TAG_arg_variable, Name,
                                  TREE_TYPE(Args), AI, Builder);
      ABIConverter.HandleArgument(TREE_TYPE(Args), ScalarArgs);
    } else {
      // Otherwise, we create an alloca to hold the argument value and provide
      // an l-value.  On entry to the function, we copy formal argument values
      // into the alloca.
      Value *Tmp = CreateTemporary(ArgTy, TYPE_ALIGN_UNIT(TREE_TYPE(Args)));
      Tmp->setName(Name + "_addr");
      SET_DECL_LOCAL(Args, Tmp);
      if (EmitDebugInfo()) {
        TheDebugInfo->EmitDeclare(Args, dwarf::DW_TAG_arg_variable, Name,
                                  TREE_TYPE(Args), Tmp, Builder);
      }

      // Emit annotate intrinsic if arg has annotate attr
      if (DECL_ATTRIBUTES(Args))
        EmitAnnotateIntrinsic(Tmp, Args);

      // Emit gcroot intrinsic if arg has attribute
      if (isa<ACCESS_TYPE>(TREE_TYPE(Args)) &&
          lookup_attribute("gcroot", TYPE_ATTRIBUTES(TREE_TYPE(Args))))
        EmitTypeGcroot(Tmp);

      Client.setName(Name);
      Client.setLocation(Tmp);
      ABIConverter.HandleArgument(TREE_TYPE(Args), ScalarArgs);
      Client.clear();
    }

    Args = Args == static_chain ? DECL_ARGUMENTS(FnDecl) : TREE_CHAIN(Args);
  }

  // Loading the value of a PARM_DECL at this point yields its initial value.
  // Remember this for use when materializing the reads implied by SSA default
  // definitions.
  SSAInsertionPoint = Builder.Insert(
      CastInst::Create(Instruction::BitCast,
                       Constant::getNullValue(Type::getInt32Ty(Context)),
                       Type::getInt32Ty(Context)),
      "ssa point");

  // If this function has nested functions, we should handle a potential
  // nonlocal_goto_save_area.
  if (cfun->nonlocal_goto_save_area) {
    // Not supported yet.
  }

  if (EmitDebugInfo())
    TheDebugInfo->EmitStopPoint(Builder.GetInsertBlock(), Builder);

  // Ensure that local variables are output in the order that they were declared
  // rather than in the order we come across them. This is only done to make the
  // IR more readable and is not needed for correctness.
  EmitVariablesInScope(DECL_INITIAL(FnDecl));
}

/// EmitVariablesInScope - Output a declaration for every variable in the
/// given scope.
void TreeToLLVM::EmitVariablesInScope(tree scope) {
  for (tree t = BLOCK_VARS(scope); t; t = TREE_CHAIN(t))
    if (isa<VAR_DECL>(t))
      // If this is just the rotten husk of a variable that the gimplifier
      // eliminated all uses of, but is preserving for debug info, ignore it.
      if (!DECL_HAS_VALUE_EXPR_P(t))
        make_decl_local(t);
  // Declare variables in contained scopes.
  for (tree t = BLOCK_SUBBLOCKS(scope); t; t = BLOCK_CHAIN(t))
    EmitVariablesInScope(t);
}

/// DefineSSAName - Use the given value as the definition of the given SSA name.
/// Returns the provided value as a convenience.
Value *TreeToLLVM::DefineSSAName(tree reg, Value *Val) {
  assert(isa<SSA_NAME>(reg) && "Not an SSA name!");
  if (Value *ExistingValue = SSANames[reg]) {
    if (Val != ExistingValue) {
      assert(isSSAPlaceholder(ExistingValue) && "Multiply defined SSA name!");
      // Replace the placeholder with the value everywhere.  This also updates
      // the map entry, because it is a TrackingVH.
      ExistingValue->replaceAllUsesWith(Val);
      delete ExistingValue;
    }
    return Val;
  }
  return SSANames[reg] = Val;
}

typedef SmallVector<std::pair<BasicBlock *, unsigned>, 8> PredVector;
typedef SmallVector<std::pair<BasicBlock *, tree>, 8> TreeVector;
typedef SmallVector<std::pair<BasicBlock *, Value *>, 8> ValueVector;

/// PopulatePhiNodes - Populate generated phi nodes with their operands.
void TreeToLLVM::PopulatePhiNodes() {
  PredVector Predecessors;
  TreeVector IncomingValues;
  ValueVector PhiArguments;

  for (unsigned Idx = 0, EIdx = (unsigned) PendingPhis.size(); Idx < EIdx;
       ++Idx) {
    // The phi node to process.
    PhiRecord &P = PendingPhis[Idx];

    // Extract the incoming value for each predecessor from the GCC phi node.
    for (unsigned i = 0, e = gimple_phi_num_args(P.gcc_phi); i != e; ++i) {
      // The incoming GCC basic block.
      basic_block bb = gimple_phi_arg_edge(P.gcc_phi, i)->src;

      // The corresponding LLVM basic block.
      DenseMap<basic_block, BasicBlock *>::iterator BI = BasicBlocks.find(bb);
      assert(BI != BasicBlocks.end() && "GCC basic block not output?");

      // The incoming GCC expression.
      tree val = gimple_phi_arg(P.gcc_phi, i)->def;

      // Associate it with the LLVM basic block.
      IncomingValues.push_back(std::make_pair(BI->second, val));

      // Several LLVM basic blocks may be generated when emitting one GCC basic
      // block.  The additional blocks always occur immediately after the main
      // basic block, and can be identified by the fact that they are nameless.
      // Associate the incoming expression with all of them, since any of them
      // may occur as a predecessor of the LLVM basic block containing the phi.
      Function::iterator FI(BI->second), FE = Fn->end();
      for (++FI; FI != FE && !FI->hasName(); ++FI) {
        assert(FI->getSinglePredecessor() == IncomingValues.back().first &&
               "Anonymous block does not continue predecessor!");
        IncomingValues.push_back(std::make_pair(FI, val));
      }
    }

    // Sort the incoming values by basic block to help speed up queries.
    std::sort(IncomingValues.begin(), IncomingValues.end());

    // Get the LLVM predecessors for the basic block containing the phi node,
    // and remember their positions in the list of predecessors (this is used
    // to avoid adding phi operands in a non-deterministic order).
    Predecessors.reserve(gimple_phi_num_args(P.gcc_phi)); // At least this many.
    BasicBlock *PhiBB = P.PHI->getParent();
    unsigned Index = 0;
    for (pred_iterator PI = pred_begin(PhiBB), PE = pred_end(PhiBB); PI != PE;
         ++PI, ++Index)
      Predecessors.push_back(std::make_pair(*PI, Index));

    if (Predecessors.empty()) {
      // FIXME: If this happens then GCC has a control flow edge where LLVM has
      // none - something has gone wrong.  For the moment be laid back about it
      // because the fact we don't yet wire up exception handling code means it
      // happens all the time in Ada and C++.
      P.PHI->replaceAllUsesWith(UndefValue::get(P.PHI->getType()));
      P.PHI->eraseFromParent();
      IncomingValues.clear();
      continue;
    }

    // Sort the predecessors by basic block.  In GCC, each predecessor occurs
    // exactly once.  However in LLVM a predecessor can occur several times,
    // and then every copy of the predecessor must be associated with exactly
    // the same incoming value in the phi node.  Sorting the predecessors groups
    // multiple occurrences together, making this easy to handle.
    std::sort(Predecessors.begin(), Predecessors.end());

    // Now iterate over the predecessors, setting phi operands as we go.
    TreeVector::iterator VI = IncomingValues.begin(), VE = IncomingValues.end();
    PredVector::iterator PI = Predecessors.begin(), PE = Predecessors.end();
    PhiArguments.resize((unsigned) Predecessors.size());
    while (PI != PE) {
      // The predecessor basic block.
      BasicBlock *BB = PI->first;

      // Find the incoming value for this predecessor.
      while (VI != VE && VI->first != BB)
        ++VI;
      assert(VI != VE && "No value for predecessor!");
      Value *Val = EmitRegister(VI->second);

      // Need to bitcast to the right type (useless_type_conversion_p).  Place
      // the bitcast at the end of the predecessor, before the terminator.
      if (Val->getType() != P.PHI->getType())
        Val = new BitCastInst(Val, P.PHI->getType(), "", BB->getTerminator());

      // Add the phi node arguments for all occurrences of this predecessor.
      do {
        // Place the argument at the position given by PI->second, which is the
        // original position before sorting of the predecessor in the pred list.
        // Since the predecessors were sorted non-deterministically (by pointer
        // value), this ensures that the same bitcode is produced on any run.
        PhiArguments[PI++->second] = std::make_pair(BB, Val);
      } while (PI != PE && PI->first == BB);
    }

    // Add the operands to the phi node.
    for (ValueVector::iterator I = PhiArguments.begin(), E = PhiArguments.end();
         I != E; ++I)
      P.PHI->addIncoming(I->second, I->first);

    IncomingValues.clear();
    PhiArguments.clear();
    Predecessors.clear();
  }

  PendingPhis.clear();
}

Function *TreeToLLVM::FinishFunctionBody() {
  if (ReturnBB) {
    // Insert the return block at the end of the function.
    BeginBlock(ReturnBB);

    SmallVector<Value *, 4> RetVals;

    // If the function returns a value, get it into a register and return it now.
    if (!Fn->getReturnType()->isVoidTy()) {
      tree TreeRetVal = DECL_RESULT(FnDecl);
      LValue ResultLV = EmitLV(TreeRetVal);
      assert(!ResultLV.isBitfield() && "Bitfields not allowed here!");

      if (!isa<AGGREGATE_TYPE>(TREE_TYPE(TreeRetVal)) &&
          !isa<COMPLEX_TYPE>(TREE_TYPE(TreeRetVal))) {
        // If the DECL_RESULT is a scalar type, just load out the return value
        // and return it.
        LoadInst *Load =
            Builder.CreateAlignedLoad(ResultLV.Ptr, ResultLV.getAlignment());
        RetVals.push_back(Builder.CreateBitCast(Load, Fn->getReturnType()));
      } else {
        uint64_t ResultSize = getDataLayout().getTypeAllocSize(
            ConvertType(TREE_TYPE(TreeRetVal)));
        uint64_t ReturnSize =
            getDataLayout().getTypeAllocSize(Fn->getReturnType());

        // The load does not necessarily start at the beginning of the aggregate
        // (x86-64).
        if (ReturnOffset >= ResultSize) {
          // Also catches the case of an empty return value.
          RetVals.push_back(UndefValue::get(Fn->getReturnType()));
        } else {
          // Advance to the point we want to load from.
          if (ReturnOffset) {
            ResultLV.Ptr = Builder
                .CreateBitCast(ResultLV.Ptr, Type::getInt8PtrTy(Context));
            ResultLV.Ptr = Builder.CreateGEP(
                ResultLV.Ptr,
                ConstantInt::get(DL.getIntPtrType(Context, 0), ReturnOffset),
                flag_verbose_asm ? "rtvl" : "");
            ResultLV.setAlignment(
                MinAlign(ResultLV.getAlignment(), ReturnOffset));
            ResultSize -= ReturnOffset;
          }

          // A place to build up the function return value.
          MemRef ReturnLoc = CreateTempLoc(Fn->getReturnType());

          // Copy out DECL_RESULT while being careful to not overrun the source or
          // destination buffers.
          uint64_t OctetsToCopy = std::min(ResultSize, ReturnSize);
          EmitMemCpy(
              ReturnLoc.Ptr, ResultLV.Ptr, Builder.getInt64(OctetsToCopy),
              std::min(ReturnLoc.getAlignment(), ResultLV.getAlignment()));

          if (StructType *STy =
                llvm::dyn_cast<StructType>(Fn->getReturnType())) {
            llvm::Value *Idxs[2];
            Idxs[0] = Builder.getInt32(0);
            bool Packed = STy->isPacked();
            for (unsigned ri = 0; ri < STy->getNumElements(); ++ri) {
              Idxs[1] = Builder.getInt32(ri);
              Value *GEP = Builder.CreateGEP(ReturnLoc.Ptr, Idxs,
                                             flag_verbose_asm ? "mrv_gep" : "");
              Value *E = Builder.CreateAlignedLoad(
                  GEP, /*Align*/ Packed, flag_verbose_asm ? "mrv" : "");
              RetVals.push_back(E);
            }
            // If the return type specifies an empty struct then return one.
            if (RetVals.empty())
              RetVals.push_back(UndefValue::get(Fn->getReturnType()));
          } else {
            // Otherwise, this aggregate result must be something that is returned
            // in a scalar register for this target.  We must bit convert the
            // aggregate to the specified scalar type, which we do by casting the
            // pointer and loading.
            RetVals.push_back(Builder.CreateLoad(ReturnLoc.Ptr, "retval"));
          }
        }
      }
    }
    if (RetVals.empty())
      Builder.CreateRetVoid();
    else if (RetVals.size() == 1 &&
             RetVals[0]->getType() == Fn->getReturnType()) {
      Builder.CreateRet(RetVals[0]);
    } else {
      assert(Fn->getReturnType()->isAggregateType() && "Return type mismatch!");
      Builder.CreateAggregateRet(RetVals.data(), (unsigned) RetVals.size());
    }
  } else { // !ReturnBB
    BasicBlock *CurBB = Builder.GetInsertBlock();
    if (CurBB->getTerminator() == 0) {
      if (CurBB->getName().empty() && CurBB->begin() == CurBB->end()) {
        // If the previous block has no label and is empty, remove it: it is a
        // post-terminator block.
        CurBB->eraseFromParent();
        Builder.SetInsertPoint(&Fn->getBasicBlockList().back());
      } else {
        // The previous block may contain code but no terminator if it finished
        // with an unsupported GCC builtin.
        Builder.CreateUnreachable();
      }
    }
  }

  // Populate phi nodes with their operands now that all ssa names have been
  // defined and all basic blocks output.
  PopulatePhiNodes();

  // Now that phi nodes have been output, emit pending exception handling code.
  EmitLandingPads();
  EmitFailureBlocks();

  if (ReturnBB) {
    // FIXME: This should be output just before the return call generated above.
    // But because EmitFunctionEnd pops the region stack, that means that if the
    // call to PopulatePhiNodes (for example) generates complicated debug info,
    // then the debug info logic barfs.  Testcases showing this are 20011126-2.c
    // or pr42221.c from the gcc testsuite compiled with -g -O3.
    if (EmitDebugInfo()) {
      TheDebugInfo->EmitStopPoint(ReturnBB, Builder);
      TheDebugInfo->EmitFunctionEnd(true);
    }
  }

#ifdef NDEBUG
  // When processing broken code it can be awkward to ensure that every SSA name
  // that was used has a definition.  So in this case we play it cool and create
  // an artificial definition for such SSA names.  The choice of definition does
  // not matter because the compiler is going to exit with an error anyway.
  if (errorcount || sorrycount)
#else
// When checks are enabled, complain if an SSA name was used but not defined.
#endif
    for (DenseMap<tree, TrackingVH<Value> >::const_iterator
             I = SSANames.begin(),
             E = SSANames.end();
         I != E; ++I) {
      Value *NameDef = I->second;
      // If this is not a placeholder then the SSA name was defined.
      if (!isSSAPlaceholder(NameDef))
        continue;

      // If an error occurred then replace the placeholder with undef.  Thanks
      // to this we can just bail out on errors, without having to worry about
      // whether we defined every SSA name.
      if (errorcount || sorrycount) {
        NameDef->replaceAllUsesWith(UndefValue::get(NameDef->getType()));
        delete NameDef;
      } else {
        debug_tree(I->first);
        llvm_unreachable("SSA name never defined!");
      }
    }

  return Fn;
}

/// getBasicBlock - Find or create the LLVM basic block corresponding to BB.
BasicBlock *TreeToLLVM::getBasicBlock(basic_block bb) {
  // If we already associated an LLVM basic block with BB, then return it.
  DenseMap<basic_block, BasicBlock *>::iterator I = BasicBlocks.find(bb);
  if (I != BasicBlocks.end())
    return I->second;

  // Otherwise, create a new LLVM basic block.
  BasicBlock *BB = BasicBlock::Create(Context);

  // All basic blocks that directly correspond to GCC basic blocks (those
  // created here) must have a name.  All artificial basic blocks produced
  // while generating code must be nameless.  That way, artificial blocks
  // can be easily identified.

  // Give the basic block a name.  If the user specified -fverbose-asm then
  // use the same naming scheme as GCC.
  if (flag_verbose_asm) {
    // If BB contains labels, name the LLVM basic block after the first label.
    gimple stmt = first_stmt(bb);
    if (stmt && gimple_code(stmt) == GIMPLE_LABEL) {
      tree label = gimple_label_label(stmt);
      const std::string &LabelName = getDescriptiveName(label);
      if (!LabelName.empty())
        BB->setName("<" + LabelName + ">");
    } else {
      // When there is no label, use the same name scheme as the GCC tree dumps.
      Twine Index(bb->index);
      BB->setName("<bb " + Index + ">");
    }
  } else {
    Twine Index(bb->index);
    BB->setName(Index);
  }

  return BasicBlocks[bb] = BB;
}

/// getLabelDeclBlock - Lazily get and create a basic block for the specified
/// label.
BasicBlock *TreeToLLVM::getLabelDeclBlock(tree LabelDecl) {
  assert(isa<LABEL_DECL>(LabelDecl) && "Isn't a label!?");
  if (DECL_LOCAL_SET_P(LabelDecl))
    return cast<BasicBlock>(DECL_LOCAL(LabelDecl));

  basic_block bb = label_to_block(LabelDecl);
  if (!bb) {
    sorry("address of a non-local label");
    bb = ENTRY_BLOCK_PTR; // Do not crash.
  }

  BasicBlock *BB = getBasicBlock(bb);
  SET_DECL_LOCAL(LabelDecl, BB);
  return BB;
}

void TreeToLLVM::EmitBasicBlock(basic_block bb) {
  location_t saved_loc = input_location;
  ++NumBasicBlocks;

  // Avoid outputting a pointless branch at the end of the entry block.
  if (bb != ENTRY_BLOCK_PTR)
    BeginBlock(getBasicBlock(bb));

  // Create an LLVM phi node for each GCC phi and define the associated ssa name
  // using it.  Do not populate with operands at this point since some ssa names
  // the phi uses may not have been defined yet - phis are special this way.
  for (gimple_stmt_iterator gsi = gsi_start_phis(bb); !gsi_end_p(gsi);
       gsi_next(&gsi)) {
    gimple gcc_phi = gsi_stmt(gsi);
    // Skip virtual operands.
    if (!is_gimple_reg(gimple_phi_result(gcc_phi)))
      continue;

    // Create the LLVM phi node.
    Type *Ty = getRegType(TREE_TYPE(gimple_phi_result(gcc_phi)));
    PHINode *PHI = Builder.CreatePHI(Ty, gimple_phi_num_args(gcc_phi));

    // The phi defines the associated ssa name.
    tree name = gimple_phi_result(gcc_phi);
    assert(isa<SSA_NAME>(name) && "PHI result not an SSA name!");
    if (flag_verbose_asm)
      NameValue(PHI, name);
    DefineSSAName(name, PHI);

    // The phi operands will be populated later - remember the phi node.
    PhiRecord P = { gcc_phi, PHI };
    PendingPhis.push_back(P);
  }

  // Render statements.
  for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi);
       gsi_next(&gsi)) {
    gimple stmt = gsi_stmt(gsi);
    input_location = gimple_location(stmt);
    ++NumStatements;

    if (EmitDebugInfo()) {
      if (gimple_has_location(stmt)) {
        TheDebugInfo->setLocationFile(gimple_filename(stmt));
        TheDebugInfo->setLocationLine(gimple_lineno(stmt));
      } else {
        TheDebugInfo->setLocationFile("");
        TheDebugInfo->setLocationLine(0);
      }
      TheDebugInfo->EmitStopPoint(Builder.GetInsertBlock(), Builder);
    }

    switch (gimple_code(stmt)) {
    default:
      debug_gimple_stmt(stmt);
      llvm_unreachable("Unhandled GIMPLE statement during LLVM emission!");

    case GIMPLE_ASM:
      RenderGIMPLE_ASM(stmt);
      break;

    case GIMPLE_ASSIGN:
      RenderGIMPLE_ASSIGN(stmt);
      break;

    case GIMPLE_CALL:
      RenderGIMPLE_CALL(stmt);
      break;

    case GIMPLE_COND:
      RenderGIMPLE_COND(stmt);
      break;

    case GIMPLE_DEBUG:
      // TODO: Output debug info rather than just discarding it.
      break;

    case GIMPLE_EH_DISPATCH:
      RenderGIMPLE_EH_DISPATCH(stmt);
      break;

    case GIMPLE_GOTO:
      RenderGIMPLE_GOTO(stmt);
      break;

    case GIMPLE_LABEL:
    case GIMPLE_NOP:
    case GIMPLE_PREDICT:
      break;

    case GIMPLE_RESX:
      RenderGIMPLE_RESX(stmt);
      break;

    case GIMPLE_RETURN:
      RenderGIMPLE_RETURN(stmt);
      break;

    case GIMPLE_SWITCH:
      RenderGIMPLE_SWITCH(stmt);
      break;
    }
  }

  if (EmitDebugInfo()) {
    TheDebugInfo->setLocationFile("");
    TheDebugInfo->setLocationLine(0);
    TheDebugInfo->EmitStopPoint(Builder.GetInsertBlock(), Builder);
  }

  // Add a branch to the fallthru block.
  edge e;
  edge_iterator ei;
  FOR_EACH_EDGE(e, ei, bb->succs) if (e->flags & EDGE_FALLTHRU) {
    input_location = e->goto_locus;
    // TODO: set the debug info location.
    Builder.CreateBr(getBasicBlock(e->dest));
    break;
  }

  input_location = saved_loc;
}

Function *TreeToLLVM::EmitFunction() {
  FastMathFlags FMF;
  if (flag_finite_math_only) {
    FMF.setNoInfs();
    FMF.setNoNaNs();
  }
  if (!flag_signed_zeros)
    FMF.setNoSignedZeros();
  if (flag_reciprocal_math)
    FMF.setAllowReciprocal();
  if (flag_unsafe_math_optimizations && flag_finite_math_only)
    FMF.setUnsafeAlgebra();
  Builder.SetFastMathFlags(FMF);

  // Set up parameters and prepare for return, for the function.
  StartFunctionBody();

  // Output the basic blocks.
  basic_block bb;
  FOR_EACH_BB(bb) EmitBasicBlock(bb);

  // Wrap things up.
  return FinishFunctionBody();
}

/// EmitAggregate - Store the specified tree node into the location given by
/// DestLoc.
void TreeToLLVM::EmitAggregate(tree exp, const MemRef &DestLoc) {
  assert(isa<AGGREGATE_TYPE>(TREE_TYPE(exp)) && "Expected an aggregate type!");
  if (isa<CONSTRUCTOR>(exp)) {
    EmitCONSTRUCTOR(exp, &DestLoc);
    return;
  }
  LValue LV = EmitLV(exp);
  assert(!LV.isBitfield() && "Bitfields containing aggregates not supported!");
  EmitAggregateCopy(DestLoc,
                    MemRef(LV.Ptr, LV.getAlignment(), TREE_THIS_VOLATILE(exp)),
                    TREE_TYPE(exp));
}

/// get_constant_alignment - Return the alignment of constant EXP in bits.
///
static unsigned int get_constant_alignment(tree exp) {
  unsigned int align = TYPE_ALIGN(TREE_TYPE(exp));
#ifdef CONSTANT_ALIGNMENT
  align = CONSTANT_ALIGNMENT(exp, align);
#endif
  return align;
}

/// EmitLV - Convert the specified l-value tree node to LLVM code, returning
/// the address of the result.
LValue TreeToLLVM::EmitLV(tree exp) {
  LValue LV;

  switch (TREE_CODE(exp)) {
  default:
    debug_tree(exp);
    llvm_unreachable("Unhandled lvalue expression!");

  case PARM_DECL:
  case VAR_DECL:
  case FUNCTION_DECL:
  case CONST_DECL:
  case RESULT_DECL:
    LV = EmitLV_DECL(exp);
    break;
  case ARRAY_RANGE_REF:
  case ARRAY_REF:
    LV = EmitLV_ARRAY_REF(exp);
    break;
  case COMPONENT_REF:
    LV = EmitLV_COMPONENT_REF(exp);
    break;
  case BIT_FIELD_REF:
    LV = EmitLV_BIT_FIELD_REF(exp);
    break;
  case REALPART_EXPR:
    LV = EmitLV_XXXXPART_EXPR(exp, 0);
    break;
  case IMAGPART_EXPR:
    LV = EmitLV_XXXXPART_EXPR(exp, 1);
    break;
  case SSA_NAME:
    LV = EmitLV_SSA_NAME(exp);
    break;
#if (GCC_MINOR > 5)
  case MEM_REF:
    LV = EmitLV_MEM_REF(exp);
    break;
#endif
  case TARGET_MEM_REF:
    LV = EmitLV_TARGET_MEM_REF(exp);
    break;

    // Constants.
  case LABEL_DECL: {
    LV = LValue(AddressOfLABEL_DECL(exp), 1);
    break;
  }
  case CONSTRUCTOR:
  case COMPLEX_CST:
  case FIXED_CST:
  case INTEGER_CST:
  case REAL_CST:
  case STRING_CST:
  case VECTOR_CST: {
    Value *Ptr = AddressOf(exp);
    LV = LValue(Ptr, get_constant_alignment(exp) / 8);
    break;
  }

    // Type Conversion.
  case VIEW_CONVERT_EXPR:
    LV = EmitLV_VIEW_CONVERT_EXPR(exp);
    break;

    // Trivial Cases.
  case WITH_SIZE_EXPR:
    LV = EmitLV_WITH_SIZE_EXPR(exp);
    break;
  case INDIRECT_REF:
    LV = EmitLV_INDIRECT_REF(exp);
    break;
#if (GCC_MINOR < 6)
  case MISALIGNED_INDIRECT_REF:
    LV = EmitLV_MISALIGNED_INDIRECT_REF(exp);
    break;
#endif
  }

  // Check that the type of the lvalue is indeed that of a pointer to the tree
  // node.  This may not hold for bitfields because the type of a bitfield need
  // not match the type of the value being loaded out of it.  Since LLVM has no
  // void* type, don't insist that void* be converted to a specific LLVM type.
  assert((LV.isBitfield() || isa<VOID_TYPE>(TREE_TYPE(exp)) ||
          LV.Ptr->getType() == ConvertType(TREE_TYPE(exp))->getPointerTo()) &&
         "LValue has wrong type!");

  return LV;
}

//===----------------------------------------------------------------------===//
//                         ... Utility Functions ...
//===----------------------------------------------------------------------===//

/// CastToAnyType - Cast the specified value to the specified type making no
/// assumptions about the types of the arguments. This creates an inferred cast.
Value *TreeToLLVM::CastToAnyType(Value *Src, bool SrcIsSigned, Type *DestTy,
                                 bool DestIsSigned) {
  Type *SrcTy = Src->getType();

  // Eliminate useless casts of a type to itself.
  if (SrcTy == DestTy)
    return Src;

  // Check whether the cast needs to be done in two steps, for example a pointer
  // to float cast requires converting the pointer to an integer before casting
  // to the float.
  if (!CastInst::isCastable(SrcTy, DestTy)) {
    unsigned SrcBits = SrcTy->getScalarSizeInBits();
    unsigned DestBits = DestTy->getScalarSizeInBits();
    if (SrcBits && !isa<IntegerType>(SrcTy)) {
      Type *IntTy = IntegerType::get(Context, SrcBits);
      Src = Builder.CreateBitCast(Src, IntTy);
      return CastToAnyType(Src, SrcIsSigned, DestTy, DestIsSigned);
    }
    if (DestBits && !isa<IntegerType>(DestTy)) {
      Type *IntTy = IntegerType::get(Context, DestBits);
      Src = CastToAnyType(Src, SrcIsSigned, IntTy, DestIsSigned);
      return Builder.CreateBitCast(Src, DestTy);
    }
    llvm_unreachable("Unable to cast between these types!");
  }

  // The types are different so we must cast. Use getCastOpcode to create an
  // inferred cast opcode.
  Instruction::CastOps opc =
      CastInst::getCastOpcode(Src, SrcIsSigned, DestTy, DestIsSigned);

  // Generate the cast and return it.
  return Builder.CreateCast(opc, Src, DestTy);
}
Constant *TreeToLLVM::CastToAnyType(Constant *Src, bool SrcIsSigned,
                                    Type *DestTy, bool DestIsSigned) {
  Type *SrcTy = Src->getType();

  // Eliminate useless casts of a type to itself.
  if (SrcTy == DestTy)
    return Src;

  // Check whether the cast needs to be done in two steps, for example a pointer
  // to float cast requires converting the pointer to an integer before casting
  // to the float.
  if (!CastInst::isCastable(SrcTy, DestTy)) {
    unsigned SrcBits = SrcTy->getScalarSizeInBits();
    unsigned DestBits = DestTy->getScalarSizeInBits();
    if (SrcBits && !isa<IntegerType>(SrcTy)) {
      Type *IntTy = IntegerType::get(Context, SrcBits);
      Src = TheFolder->CreateBitCast(Src, IntTy);
      return CastToAnyType(Src, SrcIsSigned, DestTy, DestIsSigned);
    }
    if (DestBits && !isa<IntegerType>(DestTy)) {
      Type *IntTy = IntegerType::get(Context, DestBits);
      Src = CastToAnyType(Src, SrcIsSigned, IntTy, DestIsSigned);
      return TheFolder->CreateBitCast(Src, DestTy);
    }
    llvm_unreachable("Unable to cast between these types!");
  }

  // The types are different so we must cast. Use getCastOpcode to create an
  // inferred cast opcode.
  Instruction::CastOps opc =
      CastInst::getCastOpcode(Src, SrcIsSigned, DestTy, DestIsSigned);

  // Generate the cast and return it.
  return TheFolder->CreateCast(opc, Src, DestTy);
}

/// CastFromSameSizeInteger - Cast an integer (or vector of integer) value to
/// the given scalar (resp. vector of scalar) type of the same bitwidth.
Value *TreeToLLVM::CastFromSameSizeInteger(Value *V, Type *Ty) {
  assert(V->getType()->getScalarType()->isIntegerTy() &&
         "Expected an integer type!");
  Type *EltTy = Ty->getScalarType();
  if (EltTy->isIntegerTy()) {
    // Already an integer/vector of integer - nothing to do.
    assert(V->getType() == Ty && "Integer type not same size!");
    return V;
  }
  if (EltTy->isPointerTy()) {
    // A pointer/vector of pointer - use inttoptr.
    assert(V->getType()->getScalarType()->getPrimitiveSizeInBits() ==
           DL.getPointerSizeInBits(cast<PointerType>(
               EltTy)->getAddressSpace()) && "Pointer type not same size!");
    return Builder.CreateIntToPtr(V, Ty);
  }
  // Everything else.
  assert(Ty->isFPOrFPVectorTy() && "Expected a floating point type!");
  return Builder.CreateBitCast(V, Ty); // Will catch any size mismatch.
}

/// CastToSameSizeInteger - Cast the specified scalar (or vector of scalar)
/// value to an integer (resp. vector of integer) of the same bit width.
Value *TreeToLLVM::CastToSameSizeInteger(Value *V) {
  Type *OrigTy = V->getType();
  Type *OrigEltTy = OrigTy->getScalarType();
  if (OrigEltTy->isIntegerTy())
    // Already an integer/vector of integer - nothing to do.
    return V;
  if (OrigEltTy->isPointerTy())
    // A pointer/vector of pointer - form a (vector of) pointer sized integers.
    return Builder.CreatePtrToInt(V, DL.getIntPtrType(OrigTy));
  // Everything else.
  assert(OrigEltTy->isFloatingPointTy() && "Expected a floating point type!");
  unsigned BitWidth = OrigEltTy->getPrimitiveSizeInBits();
  Type *NewEltTy = IntegerType::get(Context, BitWidth);
  if (VectorType *VecTy = llvm::dyn_cast<VectorType>(OrigTy)) {
    Type *NewTy = VectorType::get(NewEltTy, VecTy->getNumElements());
    return Builder.CreateBitCast(V, NewTy);
  }
  return Builder.CreateBitCast(V, NewEltTy);
}

/// CastToFPType - Cast the specified value to the specified type assuming
/// that V's type and Ty are floating point types. This arbitrates between
/// BitCast, FPTrunc and FPExt.
Value *TreeToLLVM::CastToFPType(Value *V, Type *Ty) {
  unsigned SrcBits = V->getType()->getPrimitiveSizeInBits();
  unsigned DstBits = Ty->getPrimitiveSizeInBits();
  if (SrcBits == DstBits)
    return V;
  Instruction::CastOps opcode =
      (SrcBits > DstBits ? Instruction::FPTrunc : Instruction::FPExt);
  return Builder.CreateCast(opcode, V, Ty);
}

/// CreateAnyAdd - Add two LLVM scalar values with the given GCC type.  Does not
/// support complex numbers.  The type is used to set overflow flags.
Value *TreeToLLVM::CreateAnyAdd(Value *LHS, Value *RHS, tree type) {
  if (isa<FLOAT_TYPE>(type))
    return Builder.CreateFAdd(LHS, RHS);
  return Builder.CreateAdd(LHS, RHS, "", hasNUW(type), hasNSW(type));
}

/// CreateAnyMul - Multiply two LLVM scalar values with the given GCC type.
/// Does not support complex numbers.  The type is used to set overflow flags.
Value *TreeToLLVM::CreateAnyMul(Value *LHS, Value *RHS, tree type) {
  if (isa<FLOAT_TYPE>(type))
    return Builder.CreateFMul(LHS, RHS);
  return Builder.CreateMul(LHS, RHS, "", hasNUW(type), hasNSW(type));
}

/// CreateAnyNeg - Negate an LLVM scalar value with the given GCC type.  Does
/// not support complex numbers.  The type is used to set overflow flags.
Value *TreeToLLVM::CreateAnyNeg(Value *V, tree type) {
  if (isa<FLOAT_TYPE>(type))
    return Builder.CreateFNeg(V);
  return Builder.CreateNeg(V, "", hasNUW(type), hasNSW(type));
}

/// CreateAnySub - Subtract two LLVM scalar values with the given GCC type.
/// Does not support complex numbers.  The type is used to set overflow flags.
Value *TreeToLLVM::CreateAnySub(Value *LHS, Value *RHS, tree type) {
  if (isa<FLOAT_TYPE>(type))
    return Builder.CreateFSub(LHS, RHS);
  return Builder.CreateSub(CastToSameSizeInteger(LHS),
                           CastToSameSizeInteger(RHS), "", hasNUW(type),
                           hasNSW(type));
}

/// CreateTemporary - Create a new alloca instruction of the specified type,
/// inserting it into the entry block and returning it.  The resulting
/// instruction's type is a pointer to the specified type.
AllocaInst *TreeToLLVM::CreateTemporary(Type *Ty, unsigned align) {
  if (AllocaInsertionPoint == 0) {
    // Create a dummy instruction in the entry block as a marker to insert new
    // alloc instructions before.  It doesn't matter what this instruction is,
    // it is dead.  This allows us to insert allocas in order without having to
    // scan for an insertion point. Use BitCast for int -> int
    AllocaInsertionPoint = CastInst::Create(
        Instruction::BitCast, Constant::getNullValue(Type::getInt32Ty(Context)),
        Type::getInt32Ty(Context), "alloca point");
    // Insert it as the first instruction in the entry block.
    Fn->begin()->getInstList()
        .insert(Fn->begin()->begin(), AllocaInsertionPoint);
  }
  return new AllocaInst(Ty, 0, align, "", AllocaInsertionPoint);
}

/// CreateTempLoc - Like CreateTemporary, but returns a MemRef.
MemRef TreeToLLVM::CreateTempLoc(Type *Ty) {
  AllocaInst *AI = CreateTemporary(Ty);
  // MemRefs do not allow alignment 0.
  if (!AI->getAlignment())
    AI->setAlignment(DL.getPrefTypeAlignment(Ty));
  return MemRef(AI, AI->getAlignment(), false);
}

/// BeginBlock - Add the specified basic block to the end of the function.  If
/// the previous block falls through into it, add an explicit branch.
void TreeToLLVM::BeginBlock(BasicBlock *BB) {
  BasicBlock *CurBB = Builder.GetInsertBlock();
  // If the previous block falls through to BB, add an explicit branch.
  if (CurBB->getTerminator() == 0) {
    // If the previous block has no label and is empty, remove it: it is a
    // post-terminator block.
    if (CurBB->getName().empty() && CurBB->begin() == CurBB->end())
      CurBB->eraseFromParent();
    else
      // Otherwise, fall through to this block.
      Builder.CreateBr(BB);
  }

  // Add this block.
  Fn->getBasicBlockList().push_back(BB);
  Builder.SetInsertPoint(BB); // It is now the current block.
}

static const unsigned TooCostly = 8;

/// CostOfAccessingAllElements - Return a number representing the cost of doing
/// an element by element copy of the specified type.  If it is clear that the
/// type should not be copied this way, for example because it has a bazillion
/// elements or contains fields of variable size, then TooCostly (or larger) is
/// returned.
static unsigned CostOfAccessingAllElements(tree type) {
  // If the type is incomplete, enormous or of variable size then don't copy it.
  if (!isInt64(TYPE_SIZE(type), true))
    return TooCostly;

  // A scalar copy has a cost of 1.
  if (!isa<AGGREGATE_TYPE>(type))
    return 1;

  // The cost of a record type is the sum of the costs of its fields.
  if (isa<RECORD_TYPE>(type)) {
    Type *Ty = ConvertType(type);
    unsigned TotalCost = 0;
    for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
      if (!isa<FIELD_DECL>(Field))
        continue;
      // If the field has no size, for example because it is a C-style variable
      // length array, then just give up.
      if (!DECL_SIZE(Field))
        return TooCostly;
      // Ignore fields of size zero.  This way, we don't give up just because
      // there is a size zero field that is not represented in the LLVM type.
      if (integer_zerop(DECL_SIZE(Field)))
        continue;
      // Bitfields are too hard - give up.
      if (isBitfield(Field))
        return TooCostly;
      // If there is no corresponding LLVM field then something funky is going
      // on - just give up.
      if (GetFieldIndex(Field, Ty) == INT_MAX)
        return TooCostly;
      TotalCost += CostOfAccessingAllElements(TREE_TYPE(Field));
      if (TotalCost >= TooCostly)
        return TooCostly;
    }
    return TotalCost;
  }

  // For array types, multiply the array length by the component cost.
  if (isa<ARRAY_TYPE>(type)) {
    // If this is an array with a funky component type then just give up.
    if (!isSizeCompatible(TREE_TYPE(type)))
      return TooCostly;
    uint64_t ArrayLength = ArrayLengthOf(type);
    if (ArrayLength >= TooCostly)
      return TooCostly;
    unsigned ComponentCost = CostOfAccessingAllElements(TREE_TYPE(type));
    if (ComponentCost >= TooCostly)
      return TooCostly;
    return ArrayLength * ComponentCost;
  }

  // Other types are not supported.
  return TooCostly;
}

/// CopyElementByElement - Recursively traverse the potentially aggregate
/// src/dest ptrs, copying all of the elements.  Helper for EmitAggregateCopy.
void TreeToLLVM::CopyElementByElement(MemRef DestLoc, MemRef SrcLoc,
                                      tree type) {
  if (!isa<AGGREGATE_TYPE>(type)) {
    // Copy scalar.
    MDNode *AliasTag = describeAliasSet(type);
    StoreRegisterToMemory(
        LoadRegisterFromMemory(SrcLoc, type, AliasTag, Builder), DestLoc, type,
        AliasTag, Builder);
    return;
  }

  if (isa<RECORD_TYPE>(type)) {
    // Ensure the source and destination are pointers to the record type.
    Type *Ty = ConvertType(type);
    DestLoc.Ptr = Builder.CreateBitCast(DestLoc.Ptr, Ty->getPointerTo());
    SrcLoc.Ptr = Builder.CreateBitCast(SrcLoc.Ptr, Ty->getPointerTo());

    // Copy each field in turn.
    for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
      if (!isa<FIELD_DECL>(Field))
        continue;
      // Ignore fields of size zero.
      if (integer_zerop(DECL_SIZE(Field)))
        continue;
      // Get the address of the field.
      int FieldIdx = GetFieldIndex(Field, Ty);
      assert(FieldIdx != INT_MAX && "Should not be copying if no LLVM field!");
      Value *DestFieldPtr = Builder.CreateStructGEP(
          DestLoc.Ptr, FieldIdx, flag_verbose_asm ? "df" : "");
      Value *SrcFieldPtr = Builder.CreateStructGEP(
          SrcLoc.Ptr, FieldIdx, flag_verbose_asm ? "sf" : "");

      // Compute the field's alignment.
      unsigned DestFieldAlign = DestLoc.getAlignment();
      unsigned SrcFieldAlign = SrcLoc.getAlignment();
      if (FieldIdx) {
        DestFieldAlign = MinAlign(DestFieldAlign, getFieldAlignment(Field));
        SrcFieldAlign = MinAlign(SrcFieldAlign, getFieldAlignment(Field));
      }

      // Copy the field.
      MemRef DestFieldLoc(DestFieldPtr, DestFieldAlign, DestLoc.Volatile);
      MemRef SrcFieldLoc(SrcFieldPtr, SrcFieldAlign, SrcLoc.Volatile);
      CopyElementByElement(DestFieldLoc, SrcFieldLoc, TREE_TYPE(Field));
    }
    return;
  }

  assert(isa<ARRAY_TYPE>(type) && "Expected an array!");

  // Turn the source and destination into pointers to the component type.
  Type *CompType = ConvertType(TREE_TYPE(type));
  DestLoc.Ptr = Builder.CreateBitCast(DestLoc.Ptr, CompType->getPointerTo());
  SrcLoc.Ptr = Builder.CreateBitCast(SrcLoc.Ptr, CompType->getPointerTo());

  // Copy each component in turn.
  unsigned ComponentBytes = getDataLayout().getTypeAllocSize(CompType);
  unsigned ArrayLength = ArrayLengthOf(type);
  for (unsigned i = 0; i != ArrayLength; ++i) {
    // Get the address of the component.
    Value *DestCompPtr = DestLoc.Ptr, *SrcCompPtr = SrcLoc.Ptr;
    if (i) {
      DestCompPtr = Builder.CreateConstInBoundsGEP1_32(
          DestCompPtr, i, flag_verbose_asm ? "da" : "");
      SrcCompPtr = Builder.CreateConstInBoundsGEP1_32(
          SrcCompPtr, i, flag_verbose_asm ? "sa" : "");
    }

    // Compute the component's alignment.
    unsigned DestCompAlign = DestLoc.getAlignment();
    unsigned SrcCompAlign = SrcLoc.getAlignment();
    if (i) {
      DestCompAlign = MinAlign(DestCompAlign, i * ComponentBytes);
      SrcCompAlign = MinAlign(SrcCompAlign, i * ComponentBytes);
    }

    // Copy the component.
    MemRef DestCompLoc(DestCompPtr, DestCompAlign, DestLoc.Volatile);
    MemRef SrcCompLoc(SrcCompPtr, SrcCompAlign, SrcLoc.Volatile);
    CopyElementByElement(DestCompLoc, SrcCompLoc, TREE_TYPE(type));
  }
}

#ifndef TARGET_DRAGONEGG_MEMCPY_COST
#define TARGET_DRAGONEGG_MEMCPY_COST 5
#endif

/// EmitAggregateCopy - Copy the elements from SrcLoc to DestLoc, using the
/// GCC type specified by GCCType to know which elements to copy.
void TreeToLLVM::EmitAggregateCopy(MemRef DestLoc, MemRef SrcLoc, tree type) {
  if (DestLoc.Ptr == SrcLoc.Ptr && !DestLoc.Volatile && !SrcLoc.Volatile)
    return; // noop copy.

  // If the type is small, copy element by element instead of using memcpy.
  unsigned Cost = CostOfAccessingAllElements(type);
  if (Cost < TooCostly && Cost < TARGET_DRAGONEGG_MEMCPY_COST) {
    CopyElementByElement(DestLoc, SrcLoc, type);
    return;
  }

  Value *TypeSize = EmitRegister(TYPE_SIZE_UNIT(type));
  EmitMemCpy(DestLoc.Ptr, SrcLoc.Ptr, TypeSize,
             std::min(DestLoc.getAlignment(), SrcLoc.getAlignment()));
}

/// ZeroElementByElement - Recursively traverse the potentially aggregate
/// DestLoc, zero'ing all of the elements.  Helper for EmitAggregateZero.
void TreeToLLVM::ZeroElementByElement(MemRef DestLoc, tree type) {
  if (!isa<AGGREGATE_TYPE>(type)) {
    // Zero scalar.
    StoreRegisterToMemory(Constant::getNullValue(getRegType(type)), DestLoc,
                          type, describeAliasSet(type), Builder);
    return;
  }

  if (isa<RECORD_TYPE>(type)) {
    // Ensure the pointer is to the record type.
    Type *Ty = ConvertType(type);
    DestLoc.Ptr = Builder.CreateBitCast(DestLoc.Ptr, Ty->getPointerTo());

    // Zero each field in turn.
    for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
      if (!isa<FIELD_DECL>(Field))
        continue;
      // Ignore fields of size zero.
      if (integer_zerop(DECL_SIZE(Field)))
        continue;
      // Get the address of the field.
      int FieldIdx = GetFieldIndex(Field, Ty);
      assert(FieldIdx != INT_MAX && "Should not be zeroing if no LLVM field!");
      Value *FieldPtr = Builder.CreateStructGEP(DestLoc.Ptr, FieldIdx,
                                                flag_verbose_asm ? "zf" : "");

      // Compute the field's alignment.
      unsigned FieldAlign = DestLoc.getAlignment();
      if (FieldIdx)
        FieldAlign = MinAlign(FieldAlign, getFieldAlignment(Field));

      // Zero the field.
      MemRef FieldLoc(FieldPtr, FieldAlign, DestLoc.Volatile);
      ZeroElementByElement(FieldLoc, TREE_TYPE(Field));
    }
    return;
  }

  assert(isa<ARRAY_TYPE>(type) && "Expected an array!");

  // Turn the pointer into a pointer to the component type.
  Type *CompType = ConvertType(TREE_TYPE(type));
  DestLoc.Ptr = Builder.CreateBitCast(DestLoc.Ptr, CompType->getPointerTo());

  // Zero each component in turn.
  unsigned ComponentBytes = getDataLayout().getTypeAllocSize(CompType);
  unsigned ArrayLength = ArrayLengthOf(type);
  for (unsigned i = 0; i != ArrayLength; ++i) {
    // Get the address of the component.
    Value *CompPtr = DestLoc.Ptr;
    if (i)
      CompPtr = Builder.CreateConstInBoundsGEP1_32(
          CompPtr, i, flag_verbose_asm ? "za" : "");

    // Compute the component's alignment.
    unsigned CompAlign = DestLoc.getAlignment();
    if (i)
      CompAlign = MinAlign(CompAlign, i * ComponentBytes);

    // Zero the component.
    MemRef CompLoc(CompPtr, CompAlign, DestLoc.Volatile);
    ZeroElementByElement(CompLoc, TREE_TYPE(type));
  }
}

#ifndef TARGET_DRAGONEGG_MEMSET_COST
#define TARGET_DRAGONEGG_MEMSET_COST 5
#endif

/// EmitAggregateZero - Zero the elements of DestLoc.
void TreeToLLVM::EmitAggregateZero(MemRef DestLoc, tree type) {
  // If the type is small, zero element by element instead of using memset.
  unsigned Cost = CostOfAccessingAllElements(type);
  if (Cost < TooCostly && Cost < TARGET_DRAGONEGG_MEMSET_COST) {
    ZeroElementByElement(DestLoc, type);
    return;
  }

  EmitMemSet(DestLoc.Ptr, Builder.getInt8(0),
             EmitRegister(TYPE_SIZE_UNIT(type)), DestLoc.getAlignment());
}

Value *TreeToLLVM::EmitMemCpy(Value *DestPtr, Value *SrcPtr, Value *Size,
                              unsigned Align) {

  Type *SBP = Type::getInt8PtrTy(Context);
  Type *IntPtr = DL.getIntPtrType(DestPtr->getType());
  Value *Ops[5] = { Builder.CreateBitCast(DestPtr, SBP),
                    Builder.CreateBitCast(SrcPtr, SBP),
                    Builder.CreateIntCast(Size, IntPtr, /*isSigned*/ true),
                    Builder.getInt32(Align), Builder.getFalse() };
  Type *ArgTypes[3] = { SBP, SBP, IntPtr };

  Builder.CreateCall(
      Intrinsic::getDeclaration(TheModule, Intrinsic::memcpy, ArgTypes), Ops);
  return Ops[0];
}

Value *TreeToLLVM::EmitMemMove(Value *DestPtr, Value *SrcPtr, Value *Size,
                               unsigned Align) {
  Type *SBP = Type::getInt8PtrTy(Context);
  Type *IntPtr = DL.getIntPtrType(DestPtr->getType());
  Value *Ops[5] = { Builder.CreateBitCast(DestPtr, SBP),
                    Builder.CreateBitCast(SrcPtr, SBP),
                    Builder.CreateIntCast(Size, IntPtr, /*isSigned*/ true),
                    Builder.getInt32(Align), Builder.getFalse() };
  Type *ArgTypes[3] = { SBP, SBP, IntPtr };

  Builder.CreateCall(
      Intrinsic::getDeclaration(TheModule, Intrinsic::memmove, ArgTypes), Ops);
  return Ops[0];
}

Value *TreeToLLVM::EmitMemSet(Value *DestPtr, Value *SrcVal, Value *Size,
                              unsigned Align) {
  Type *SBP = Type::getInt8PtrTy(Context);
  Type *IntPtr = DL.getIntPtrType(DestPtr->getType());
  Value *Ops[5] = { Builder.CreateBitCast(DestPtr, SBP),
                    Builder.CreateIntCast(SrcVal, Type::getInt8Ty(Context),
                                          /*isSigned*/ true),
                    Builder.CreateIntCast(Size, IntPtr, /*isSigned*/ true),
                    Builder.getInt32(Align), Builder.getFalse() };
  Type *ArgTypes[2] = { SBP, IntPtr };

  Builder.CreateCall(
      Intrinsic::getDeclaration(TheModule, Intrinsic::memset, ArgTypes), Ops);
  return Ops[0];
}

// Emits code to do something for a type attribute
void TreeToLLVM::EmitTypeGcroot(Value *V) {
  // GC intrinsics can only be used in functions which specify a collector.
  Fn->setGC("shadow-stack");

  Function *gcrootFun = Intrinsic::getDeclaration(TheModule, Intrinsic::gcroot);

  // The idea is that it's a pointer to type "Value"
  // which is opaque* but the routine expects i8** and i8*.
  PointerType *Ty = Type::getInt8PtrTy(Context);
  V = Builder.CreateBitCast(V, Ty->getPointerTo());

  Value *Ops[2] = { V, ConstantPointerNull::get(Ty) };

  Builder.CreateCall(gcrootFun, Ops);
}

// Emits annotate intrinsic if the decl has the annotate attribute set.
void TreeToLLVM::EmitAnnotateIntrinsic(Value *V, tree decl) {

  // Handle annotate attribute on global.
  tree annotateAttr = lookup_attribute("annotate", DECL_ATTRIBUTES(decl));

  if (!annotateAttr)
    return;

  Function *annotateFun =
      Intrinsic::getDeclaration(TheModule, Intrinsic::var_annotation);

  // Get file and line number
  Constant *lineNo =
      ConstantInt::get(Type::getInt32Ty(Context), DECL_SOURCE_LINE(decl));
  Constant *file = ConvertMetadataStringToGV(DECL_SOURCE_FILE(decl));
  Type *SBP = Type::getInt8PtrTy(Context);
  file = TheFolder->CreateBitCast(file, SBP);

  // There may be multiple annotate attributes. Pass return of lookup_attr
  //  to successive lookups.
  while (annotateAttr) {

    // Each annotate attribute is a tree list.
    // Get value of list which is our linked list of args.
    tree args = TREE_VALUE(annotateAttr);

    // Each annotate attribute may have multiple args.
    // Treat each arg as if it were a separate annotate attribute.
    for (tree a = args; a; a = TREE_CHAIN(a)) {
      // Each element of the arg list is a tree list, so get value
      tree val = TREE_VALUE(a);

      // Assert its a string, and then get that string.
      assert(isa<STRING_CST>(val) &&
             "Annotate attribute arg should always be a string");
      Constant *strGV = AddressOf(val);
      Value *Ops[4] = { Builder.CreateBitCast(V, SBP),
                        Builder.CreateBitCast(strGV, SBP), file, lineNo };

      Builder.CreateCall(annotateFun, Ops);
    }

    // Get next annotate attribute.
    annotateAttr = TREE_CHAIN(annotateAttr);
    if (annotateAttr)
      annotateAttr = lookup_attribute("annotate", annotateAttr);
  }
}

//===----------------------------------------------------------------------===//
//                  ... Basic Lists and Binding Scopes ...
//===----------------------------------------------------------------------===//

/// EmitAutomaticVariableDecl - Emit the function-local decl to the current
/// function and set DECL_LOCAL for the decl to the right pointer.
void TreeToLLVM::EmitAutomaticVariableDecl(tree decl) {
  // If this is just the rotten husk of a variable that the gimplifier
  // eliminated all uses of, but is preserving for debug info, ignore it.
  if (isa<VAR_DECL>(decl) && DECL_HAS_VALUE_EXPR_P(decl))
    return;

  tree type = TREE_TYPE(decl);
  Type *Ty;        // Type to allocate
  Value *Size = 0; // Amount to alloca (null for 1)

  if (DECL_SIZE(decl) == 0) { // Variable with incomplete type.
    if (DECL_INITIAL(decl) == 0)
      return; // Error message was already done; now avoid a crash.
    debug_tree(decl);
    llvm_unreachable("Initializer will decide the size of this array?");
  } else if (isa<INTEGER_CST>(DECL_SIZE_UNIT(decl))) {
    // Variable of fixed size that goes on the stack.
    Ty = ConvertType(type);
  } else {
    // Compute the variable's size in bytes.
    Size = EmitRegister(DECL_SIZE_UNIT(decl));
    Ty = Type::getInt8Ty(Context);
  }

  unsigned Alignment = DECL_ALIGN(decl) / 8; // Alignment in octets.
  assert(Alignment != 0 && "Local variable with unknown alignment!");

  // If this is the alignment we would have given the variable anyway and it was
  // not user specified then don't use an explicit alignment, making the IR look
  // more portable.
  if (!DECL_USER_ALIGN(decl) &&
      Alignment == getDataLayout().getABITypeAlignment(Ty))
    Alignment = 0;

  // Insert an alloca for this variable.
  AllocaInst *AI;
  if (!Size) { // Fixed size alloca -> entry block.
    AI = CreateTemporary(Ty);
  } else {
    AI = Builder.CreateAlloca(Ty, Size);
  }
  NameValue(AI, decl);

  AI->setAlignment(Alignment);

  SET_DECL_LOCAL(decl, AI);

  // Handle annotate attributes
  if (DECL_ATTRIBUTES(decl))
    EmitAnnotateIntrinsic(AI, decl);

  // Handle gcroot attribute
  if (isa<ACCESS_TYPE>(TREE_TYPE(decl)) &&
      lookup_attribute("gcroot", TYPE_ATTRIBUTES(TREE_TYPE(decl)))) {
    // We should null out local variables so that a stack crawl
    // before initialization doesn't get garbage results to follow.
    Type *T = cast<PointerType>(AI->getType())->getElementType();
    EmitTypeGcroot(AI);
    Builder.CreateStore(Constant::getNullValue(T), AI);
  }

  if (EmitDebugInfo()) {
    if (DECL_NAME(decl) || isa<RESULT_DECL>(decl)) {
      TheDebugInfo->EmitDeclare(decl, dwarf::DW_TAG_auto_variable,
                                AI->getName(), TREE_TYPE(decl), AI, Builder);
    }
  }
}

//===----------------------------------------------------------------------===//
//                           ... Control Flow ...
//===----------------------------------------------------------------------===//

/// ConvertTypeInfo - Convert an exception handling type info into a pointer to
/// the associated runtime type info object.
static Constant *ConvertTypeInfo(tree type) {
  // TODO: Once pass_ipa_free_lang is made a default pass, remove the call to
  // lookup_type_for_runtime below.
  if (isa<TYPE>(type))
    type = lookup_type_for_runtime(type);
  STRIP_NOPS(type);
  if (isa<ADDR_EXPR>(type))
    type = TREE_OPERAND(type, 0);
  return AddressOf(type);
}

/// getExceptionPtr - Return the local holding the exception pointer for the
/// given exception handling region, creating it if necessary.
AllocaInst *TreeToLLVM::getExceptionPtr(int RegionNo) {
  assert(RegionNo >= 0 && "Invalid exception handling region!");

  if ((unsigned) RegionNo >= ExceptionPtrs.size())
    ExceptionPtrs.resize(RegionNo + 1, 0);

  AllocaInst *&ExceptionPtr = ExceptionPtrs[RegionNo];

  if (!ExceptionPtr) {
    ExceptionPtr = CreateTemporary(Type::getInt8PtrTy(Context));
    ExceptionPtr->setName("exc_tmp");
  }

  return ExceptionPtr;
}

/// getExceptionFilter - Return the local holding the filter value for the
/// given exception handling region, creating it if necessary.
AllocaInst *TreeToLLVM::getExceptionFilter(int RegionNo) {
  assert(RegionNo >= 0 && "Invalid exception handling region!");

  if ((unsigned) RegionNo >= ExceptionFilters.size())
    ExceptionFilters.resize(RegionNo + 1, 0);

  AllocaInst *&ExceptionFilter = ExceptionFilters[RegionNo];

  if (!ExceptionFilter) {
    ExceptionFilter = CreateTemporary(Type::getInt32Ty(Context));
    ExceptionFilter->setName("filt_tmp");
  }

  return ExceptionFilter;
}

/// getFailureBlock - Return the basic block containing the failure code for
/// the given exception handling region, creating it if necessary.
BasicBlock *TreeToLLVM::getFailureBlock(int RegionNo) {
  assert(RegionNo >= 0 && "Invalid exception handling region!");

  if ((unsigned) RegionNo >= FailureBlocks.size())
    FailureBlocks.resize(RegionNo + 1, 0);

  BasicBlock *&FailureBlock = FailureBlocks[RegionNo];

  if (!FailureBlock)
    FailureBlock = BasicBlock::Create(Context, "fail");

  return FailureBlock;
}

/// EmitLandingPads - Emit EH landing pads.
void TreeToLLVM::EmitLandingPads() {
  // If there are no invokes then there is nothing to do.
  if (NormalInvokes.empty())
    return;

  // If a GCC post landing pad is shared by several exception handling regions,
  // or if there is a normal edge to it, then create LLVM landing pads for each
  // eh region.  The landing pad instruction will then go in the LLVM landing
  // pad, which then branches to the GCC post landing pad.
  for (unsigned LPadNo = 1; LPadNo < NormalInvokes.size(); ++LPadNo) {
    // Get the list of invokes for this GCC landing pad.
    SmallVector<InvokeInst *, 8> &InvokesForPad = NormalInvokes[LPadNo];

    if (InvokesForPad.empty())
      continue;

    // All of the invokes unwind to the GCC post landing pad.
    BasicBlock *PostPad = InvokesForPad[0]->getUnwindDest();

    // If the number of invokes is equal to the number of predecessors of the
    // post landing pad then it follows that no other GCC landing pad has any
    // invokes that unwind to this post landing pad, and also that no normal
    // edges land at this post pad.  In this case there is no need to create
    // an LLVM specific landing pad.
    if ((unsigned) std::distance(pred_begin(PostPad), pred_end(PostPad)) ==
        InvokesForPad.size())
      continue;

    // Create the LLVM landing pad right before the GCC post landing pad.
    BasicBlock *LPad = BasicBlock::Create(Context, "lpad", Fn, PostPad);

    // Redirect invoke unwind edges from the GCC post landing pad to LPad.
    for (unsigned i = 0, e = InvokesForPad.size(); i < e; ++i)
      InvokesForPad[i]->setSuccessor(1, LPad);

    // If there are any PHI nodes in PostPad, we need to update them to merge
    // incoming values from LPad instead.
    pred_iterator PB = pred_begin(LPad), PE = pred_end(LPad);
    for (BasicBlock::iterator II = PostPad->begin(); isa<PHINode>(II);) {
      PHINode *PN = cast<PHINode>(II++);

      // Check to see if all of the values coming in via invoke unwind edges are
      // the same.  If so, we don't need to create a new PHI node.
      Value *InVal = PN->getIncomingValueForBlock(*PB);
      for (pred_iterator PI = PB; PI != PE; ++PI) {
        if (PI != PB && InVal != PN->getIncomingValueForBlock(*PI)) {
          InVal = 0;
          break;
        }
      }

      if (InVal == 0) {
        // Different unwind edges have different values.  Create a new PHI node
        // in LPad.
        PHINode *NewPN = PHINode::Create(PN->getType(), std::distance(PB, PE),
                                         PN->getName() + ".lpad", LPad);
        // Add an entry for each unwind edge, using the value from the old PHI.
        for (pred_iterator PI = PB; PI != PE; ++PI)
          NewPN->addIncoming(PN->getIncomingValueForBlock(*PI), *PI);

        // Now use this new PHI as the common incoming value for LPad in PN.
        InVal = NewPN;
      }

      // Revector exactly one entry in the PHI node to come from LPad and
      // delete the entries that came from the invoke unwind edges.
      for (pred_iterator PI = PB; PI != PE; ++PI)
        PN->removeIncomingValue(*PI);
      PN->addIncoming(InVal, LPad);
    }

    // Add a fallthrough from LPad to the original landing pad.
    BranchInst::Create(PostPad, LPad);
  }

  // Create the landing pad instruction for each exception handling region at
  // the start of the corresponding landing pad.  At this point each exception
  // handling region has its own landing pad, which is only reachable via the
  // unwind edges of the region's invokes.
  Type *UnwindDataTy =
      StructType::get(Builder.getInt8PtrTy(), Builder.getInt32Ty(), NULL);
  for (unsigned LPadNo = 1; LPadNo < NormalInvokes.size(); ++LPadNo) {
    // Get the list of invokes for this GCC landing pad.
    SmallVector<InvokeInst *, 8> &InvokesForPad = NormalInvokes[LPadNo];

    if (InvokesForPad.empty())
      continue;

    // All of the invokes unwind to the the landing pad.
    BasicBlock *LPad = InvokesForPad[0]->getUnwindDest();

    // The exception handling region this landing pad is for.
    eh_region region = get_eh_region_from_lp_number(LPadNo);
    assert(region->index > 0 && "Invalid landing pad region!");
    unsigned RegionNo = region->index;

    // Insert instructions at the start of the landing pad, but after any phis.
    Builder.SetInsertPoint(LPad, LPad->getFirstNonPHI());

    // Create the landingpad instruction without any clauses.  Clauses are added
    // below.
    tree personality = DECL_FUNCTION_PERSONALITY(FnDecl);
    if (!personality) {
      assert(function_needs_eh_personality(cfun) == eh_personality_any &&
             "No exception handling personality!");
      personality = lang_hooks.eh_personality();
    }
    LandingPadInst *LPadInst = Builder.CreateLandingPad(
        UnwindDataTy, DECL_LLVM(personality), 0, "exc");

    // Store the exception pointer if made use of elsewhere.
    if (RegionNo < ExceptionPtrs.size() && ExceptionPtrs[RegionNo]) {
      Value *ExcPtr = Builder.CreateExtractValue(LPadInst, 0, "exc_ptr");
      Builder.CreateStore(ExcPtr, ExceptionPtrs[RegionNo]);
    }

    // Store the selector value if made use of elsewhere.
    if (RegionNo < ExceptionFilters.size() && ExceptionFilters[RegionNo]) {
      Value *Filter = Builder.CreateExtractValue(LPadInst, 1, "filter");
      Builder.CreateStore(Filter, ExceptionFilters[RegionNo]);
    }

    // Add clauses to the landing pad instruction.
    bool AllCaught = false; // Did we see a catch-all or no-throw?
    SmallSet<Constant *, 8> AlreadyCaught; // Typeinfos known caught already.
    for (; region && !AllCaught; region = region->outer)
      switch (region->type) {
      case ERT_ALLOWED_EXCEPTIONS: {
        // Filter.  Compute the list of type infos.
        AllCaught = true;
        std::vector<Constant *> TypeInfos;
        for (tree type = region->u.allowed.type_list; type;
             type = TREE_CHAIN(type)) {
          Constant *TypeInfo = ConvertTypeInfo(TREE_VALUE(type));
          // No point in letting a typeinfo through if we know it can't reach
          // the filter in the first place.
          if (AlreadyCaught.count(TypeInfo))
            continue;
          TypeInfo = TheFolder->CreateBitCast(TypeInfo, Builder.getInt8PtrTy());
          TypeInfos.push_back(TypeInfo);
          AllCaught = false;
        }

        // Add the list of typeinfos as a filter clause.
        ArrayType *FilterTy =
            ArrayType::get(Builder.getInt8PtrTy(), TypeInfos.size());
        LPadInst->addClause(ConstantArray::get(FilterTy, TypeInfos));
        break;
      }
      case ERT_CLEANUP:
        LPadInst->setCleanup(true);
        break;
      case ERT_MUST_NOT_THROW: {
        // Same as a zero-length filter: add an empty filter clause.
        ArrayType *FilterTy = ArrayType::get(Builder.getInt8PtrTy(), 0);
        LPadInst->addClause(
            ConstantArray::get(FilterTy, ArrayRef<Constant *>()));
        AllCaught = true;
        break;
      }
      case ERT_TRY:
        // Catches.
        for (eh_catch c = region->u.eh_try.first_catch; c; c = c->next_catch)
          if (!c->type_list) {
            // Catch-all - add a null pointer as a catch clause.
            LPadInst->addClause(Constant::getNullValue(Builder.getInt8PtrTy()));
            AllCaught = true;
            break;
          } else {
            // Add the type infos.
            for (tree type = c->type_list; type; type = TREE_CHAIN(type)) {
              Constant *TypeInfo = ConvertTypeInfo(TREE_VALUE(type));
              // No point in trying to catch a typeinfo that was already caught.
              if (!AlreadyCaught.insert(TypeInfo).second)
                continue;
              LPadInst->addClause(TypeInfo);
            }
          }
        break;
      }
  }

  NormalInvokes.clear();
}

/// EmitFailureBlocks - Emit the blocks containing failure code executed when
/// an exception is thrown in a must-not-throw region.
void TreeToLLVM::EmitFailureBlocks() {
  for (unsigned RegionNo = 1; RegionNo < FailureBlocks.size(); ++RegionNo) {
    BasicBlock *FailureBlock = FailureBlocks[RegionNo];

    if (!FailureBlock)
      continue;

    eh_region region = get_eh_region_from_number(RegionNo);
    assert(region->type == ERT_MUST_NOT_THROW && "Unexpected region type!");

    // Check whether all predecessors are invokes or not.  Nothing exotic can
    // occur here, only direct branches and unwinding via an invoke.
    bool hasBranchPred = false;
    bool hasInvokePred = false;
    for (pred_iterator I = pred_begin(FailureBlock), E = pred_end(FailureBlock);
         I != E && (!hasInvokePred || !hasBranchPred); ++I) {
      TerminatorInst *T = (*I)->getTerminator();
      if (isa<InvokeInst>(T)) {
        assert(FailureBlock != T->getSuccessor(0) && "Expected unwind target!");
        hasInvokePred = true;
      } else {
        assert(isa<BranchInst>(T) && "Wrong kind of failure predecessor!");
        hasBranchPred = true;
      }
    }
    assert((hasBranchPred || hasInvokePred) && "No predecessors!");

    // Determine the landing pad that invokes will unwind to.  If there are no
    // invokes, then there is no landing pad.
    BasicBlock *LandingPad = NULL;
    if (hasInvokePred) {
      // If all predecessors are invokes, then the failure block can be used as
      // the landing pad.  Otherwise, create a landing pad.
      if (hasBranchPred)
        LandingPad = BasicBlock::Create(Context, "pad");
      else
        LandingPad = FailureBlock;
    }

    if (LandingPad) {
      BeginBlock(LandingPad);

      // Generate a landingpad instruction with an empty (i.e. catch-all) filter
      // clause.
      Type *UnwindDataTy =
          StructType::get(Builder.getInt8PtrTy(), Builder.getInt32Ty(), NULL);
      tree personality = DECL_FUNCTION_PERSONALITY(FnDecl);
      assert(personality && "No-throw region but no personality function!");
      LandingPadInst *LPadInst = Builder.CreateLandingPad(
          UnwindDataTy, DECL_LLVM(personality), 1, "exc");
      ArrayType *FilterTy = ArrayType::get(Builder.getInt8PtrTy(), 0);
      LPadInst->addClause(ConstantArray::get(FilterTy, ArrayRef<Constant *>()));

      if (LandingPad != FailureBlock) {
        // Make sure all invokes unwind to the new landing pad.
        for (pred_iterator I = pred_begin(FailureBlock),
                           E = pred_end(FailureBlock);
             I != E;) {
          TerminatorInst *T = (*I++)->getTerminator();
          if (isa<InvokeInst>(T))
            T->setSuccessor(1, LandingPad);
        }

        // Branch to the failure block at the end of the landing pad.
        Builder.CreateBr(FailureBlock);
      }
    }

    if (LandingPad != FailureBlock)
      BeginBlock(FailureBlock);

    // Determine the failure function to call.
    Value *FailFunc = DECL_LLVM(region->u.must_not_throw.failure_decl);

    // Make sure it has the right type.
    FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), false);
    FailFunc = Builder.CreateBitCast(FailFunc, FTy->getPointerTo());

    // Spank the user for being naughty.
    // TODO: Set the correct debug location.
    CallInst *FailCall = Builder.CreateCall(FailFunc);

    // This is always fatal.
    FailCall->setDoesNotReturn();
    FailCall->setDoesNotThrow();
    Builder.CreateUnreachable();
  }
}

//===----------------------------------------------------------------------===//
//                           ... Expressions ...
//===----------------------------------------------------------------------===//

static bool canEmitRegisterVariable(tree exp) {
  // Only variables can be marked as 'register'.
  if (!isa<VAR_DECL>(exp) || !DECL_REGISTER(exp))
    return false;

  // We can emit inline assembler for access to global register variables.
  if (TREE_STATIC(exp) || DECL_EXTERNAL(exp) || TREE_PUBLIC(exp))
    return true;

  // Emit inline asm if this is local variable with assembler name on it.
  if (DECL_ASSEMBLER_NAME_SET_P(exp))
    return true;

  // Otherwise - it's normal automatic variable.
  return false;
}

/// EmitLoadOfLValue - When an l-value expression is used in a context that
/// requires an r-value, this method emits the lvalue computation, then loads
/// the result.
Value *TreeToLLVM::EmitLoadOfLValue(tree exp) {
  if (canEmitRegisterVariable(exp))
    // If this is a register variable, EmitLV can't handle it (there is no
    // l-value of a register variable).  Emit an inline asm node that copies the
    // value out of the specified register.
    return EmitReadOfRegisterVariable(exp);

  LValue LV = EmitLV(exp);
  LV.Volatile = TREE_THIS_VOLATILE(exp);
  // TODO: Arrange for Volatile to already be set in the LValue.
  unsigned Alignment = LV.getAlignment();

  tree type = TREE_TYPE(exp);
  if (!LV.isBitfield())
    // Scalar value: emit a load.
    return LoadRegisterFromMemory(LV, type, describeAliasSet(exp), Builder);

  // This is a bitfield reference.
  Type *Ty = getRegType(type);
  if (!LV.BitSize)
    return Constant::getNullValue(Ty);

  // Load the minimum number of bytes that covers the field.
  unsigned LoadSizeInBits = LV.BitStart + LV.BitSize;
  LoadSizeInBits = RoundUpToAlignment(LoadSizeInBits, BITS_PER_UNIT);
  Type *LoadType = IntegerType::get(Context, LoadSizeInBits);

  // Load the bits.
  Value *Ptr = Builder.CreateBitCast(LV.Ptr, LoadType->getPointerTo());
  Value *Val = Builder.CreateAlignedLoad(Ptr, Alignment, LV.Volatile);

  // Mask the bits out by shifting left first, then shifting right.  The
  // optimizers will turn this into an "and" in the unsigned case.

  // Shift the sign bit of the bitfield to the sign bit position in the loaded
  // type.  This zaps any extra bits occurring after the end of the bitfield.
  unsigned FirstBitInVal =
      BYTES_BIG_ENDIAN ? LoadSizeInBits - LV.BitStart - LV.BitSize
                       : LV.BitStart;
  if (FirstBitInVal + LV.BitSize != LoadSizeInBits) {
    Value *ShAmt = ConstantInt::get(LoadType, LoadSizeInBits -
                                              (FirstBitInVal + LV.BitSize));
    Val = Builder.CreateShl(Val, ShAmt);
  }
  // Shift the first bit of the bitfield to be bit zero.  This zaps any extra
  // bits that occurred before the start of the bitfield.  In the signed case
  // this also duplicates the sign bit, giving a sign extended value.
  bool isSigned = !TYPE_UNSIGNED(type);
  Value *ShAmt = ConstantInt::get(LoadType, LoadSizeInBits - LV.BitSize);
  Val = isSigned ? Builder.CreateAShr(Val, ShAmt)
                 : Builder.CreateLShr(Val, ShAmt);

  // Get the bits as an integer with the same in-memory size as the result.
  // Extending the integer with defined bits (rather than storing it as is to
  // the temporary, which in effect extends with undefined bits) is required
  // in order to get the right result for C-like languages.
  unsigned MemSize = GET_MODE_BITSIZE(TYPE_MODE(type));
  Type *ResIntTy = IntegerType::get(Context, MemSize);
  Value *ResInt = Builder.CreateIntCast(Val, ResIntTy, isSigned);

  // Create the temporary, an integer.  Ensure it is sufficiently aligned for
  // both the integer and the real type.  Store the bits to it.
  Alignment = std::max(TYPE_ALIGN(type) / 8,
                       DL.getPrefTypeAlignment(ResIntTy));
  MemRef Tmp(CreateTemporary(ResIntTy, Alignment), Alignment, false);
  Builder.CreateStore(ResInt, Tmp.Ptr);

  // At this point we have in essence just displaced the original set of bits to
  // a new memory location that is byte aligned, from which we now trivially load
  // the desired value.
  return LoadRegisterFromMemory(Tmp, type, 0, Builder);
}

Value *TreeToLLVM::EmitADDR_EXPR(tree exp) {
  LValue LV = EmitLV(TREE_OPERAND(exp, 0));
  assert((!LV.isBitfield() || LV.BitStart == 0) &&
         "It is illegal to take the address of a bitfield!");
  // Perform a cast here if necessary.  For example, GCC sometimes forms an
  // ADDR_EXPR where the operand is an array, and the ADDR_EXPR type is a
  // pointer to the first element.
  return Builder.CreateBitCast(LV.Ptr, getRegType(TREE_TYPE(exp)));
}

#if (GCC_MINOR < 7)
Value *TreeToLLVM::EmitCondExpr(tree exp) {
  return TriviallyTypeConvert(
      EmitReg_CondExpr(TREE_OPERAND(exp, 0), TREE_OPERAND(exp, 1),
                       TREE_OPERAND(exp, 2)),
      getRegType(TREE_TYPE(exp)));
}
#endif

Value *TreeToLLVM::EmitOBJ_TYPE_REF(tree exp) {
  return Builder.CreateBitCast(EmitRegister(OBJ_TYPE_REF_EXPR(exp)),
                               getRegType(TREE_TYPE(exp)));
}

#if (GCC_MINOR < 8)
INSTANTIATE_VECTOR(constructor_elt);
#endif

/// EmitCONSTRUCTOR - emit the constructor into the location specified by
/// DestLoc.
Value *TreeToLLVM::EmitCONSTRUCTOR(tree exp, const MemRef *DestLoc) {
  tree type = TREE_TYPE(exp);
  Type *Ty = ConvertType(type);
  if (VectorType *VTy = llvm::dyn_cast<VectorType>(Ty)) {
    assert(DestLoc == 0 && "Dest location for vector value?");
    std::vector<Value *> BuildVecOps;
    BuildVecOps.reserve(VTy->getNumElements());

    // Insert all of the elements here.
    unsigned HOST_WIDE_INT idx;
    tree value;
    FOR_EACH_CONSTRUCTOR_VALUE(CONSTRUCTOR_ELTS(exp), idx, value) {
      Value *Elt = EmitRegister(value);

      if (VectorType *EltTy = llvm::dyn_cast<VectorType>(Elt->getType())) {
        // GCC allows vectors to be built up from vectors.  Extract all of the
        // vector elements and add them to the list of build vector operands.
        for (unsigned i = 0, e = EltTy->getNumElements(); i != e; ++i) {
          Value *Index = Builder.getInt32(i);
          BuildVecOps.push_back(Builder.CreateExtractElement(Elt, Index));
        }
      } else {
        assert(Elt->getType() == VTy->getElementType() &&
               "Unexpected type for vector constructor!");
        BuildVecOps.push_back(Elt);
      }
    }

    // Insert zero for any unspecified values.
    while (BuildVecOps.size() < VTy->getNumElements())
      BuildVecOps.push_back(Constant::getNullValue(VTy->getElementType()));
    assert(BuildVecOps.size() == VTy->getNumElements() &&
           "Vector constructor specified too many values!");

    return BuildVector(BuildVecOps);
  }

  assert(isa<AGGREGATE_TYPE>(type) && "Constructor for scalar type??");

  // Start out with the value zero'd out.
  EmitAggregateZero(*DestLoc, type);

  if (!CONSTRUCTOR_ELTS(exp))
    return 0; // No elements.

  const vec<constructor_elt, va_gc> &elt = *CONSTRUCTOR_ELTS(exp);

  if (elt.is_empty())
    return 0; // No elements.

  switch (TREE_CODE(TREE_TYPE(exp))) {
  case ARRAY_TYPE:
  case RECORD_TYPE:
  default:
    debug_tree(exp);
    llvm_unreachable("We don't handle elements yet!");
  case QUAL_UNION_TYPE:
  case UNION_TYPE:
    // Store each element of the constructor into the corresponding field of
    // DEST.
    assert(elt.length() == 1 && "Union CONSTRUCTOR should have one element!");
    tree tree_purpose = elt[0].index;
    tree tree_value = elt[0].value;
    if (!tree_purpose)
      return 0; // Not actually initialized?

    if (isa<AGGREGATE_TYPE>(TREE_TYPE(tree_purpose))) {
      EmitAggregate(tree_value, *DestLoc);
    } else {
      // Scalar value.  Evaluate to a register, then do the store.
      Value *V = EmitRegister(tree_value);
      StoreRegisterToMemory(V, *DestLoc, TREE_TYPE(tree_purpose), 0, Builder);
    }
    break;
  }
  return 0;
}

/// llvm_load_scalar_argument - Load value located at LOC.
static Value *llvm_load_scalar_argument(
    Value *L, llvm::Type *LLVMTy, unsigned RealSize, LLVMBuilder &Builder) {
  if (!RealSize)
    return UndefValue::get(LLVMTy);

  // Not clear what this is supposed to do on big endian machines...
  assert(!BYTES_BIG_ENDIAN && "Unsupported case - please report");
  assert(LLVMTy->isIntegerTy() && "Expected an integer value!");
  Type *LoadType = IntegerType::get(Context, RealSize * 8);
  L = Builder.CreateBitCast(L, LoadType->getPointerTo());
  Value *Val = Builder.CreateLoad(L);
  if (LoadType->getPrimitiveSizeInBits() >= LLVMTy->getPrimitiveSizeInBits())
    Val = Builder.CreateTrunc(Val, LLVMTy);
  else
    Val = Builder.CreateZExt(Val, LLVMTy);
  return Val;
}

#ifndef LLVM_LOAD_SCALAR_ARGUMENT
#define LLVM_LOAD_SCALAR_ARGUMENT(LOC, TY, SIZE, BUILDER)                      \
  llvm_load_scalar_argument((LOC), (TY), (SIZE), (BUILDER))
#endif

namespace {
/// FunctionCallArgumentConversion - This helper class is driven by the ABI
/// definition for this target to figure out how to pass arguments into the
/// stack/regs for a function call.
struct FunctionCallArgumentConversion : public DefaultABIClient {
  SmallVector<Value *, 16> &CallOperands;
  SmallVector<Value *, 2> LocStack;
  FunctionType *FTy;
  const MemRef *DestLoc;
  LLVMBuilder &Builder;
  Value *TheValue;
  MemRef RetBuf;
  CallingConv::ID &CallingConv;
  unsigned Offset;
  bool isShadowRet;
  bool isAggrRet;
  bool useReturnSlot;

  FunctionCallArgumentConversion(
      SmallVector<Value *, 16> &ops, FunctionType *FnTy, const MemRef *destloc,
      bool ReturnSlotOpt, LLVMBuilder &b, CallingConv::ID &CC)
      : CallOperands(ops), FTy(FnTy), DestLoc(destloc), Builder(b),
        CallingConv(CC), Offset(0), isShadowRet(false), isAggrRet(false),
        useReturnSlot(ReturnSlotOpt) {}

  /// getCallingConv - This provides the desired CallingConv for the function.
  CallingConv::ID getCallingConv(void) { return CallingConv; }

  // Push the address of an argument.
  void pushAddress(Value *Loc) {
    assert(Loc && "Invalid location!");
    LocStack.push_back(Loc);
  }

  // Push the value of an argument.
  void pushValue(Value *V) {
    assert(LocStack.empty() && "Value only allowed at top level!");
    LocStack.push_back(NULL);
    TheValue = V;
  }

  // Get the address of the current location.
  Value *getAddress(void) {
    assert(!LocStack.empty());
    Value *&Loc = LocStack.back();
    if (!Loc) {
      // A value.  Store to a temporary, and return the temporary's address.
      // Any future access to this argument will reuse the same address.
      Loc = TheTreeToLLVM->CreateTemporary(TheValue->getType());
      Builder.CreateStore(TheValue, Loc);
    }
    return Loc;
  }

  // Get the value of the current location (of type Ty).
  Value *getValue(Type *Ty) {
    assert(!LocStack.empty());
    Value *Loc = LocStack.back();
    if (Loc) {
      // An address.  Convert to the right type and load the value out.
      Loc = Builder.CreateBitCast(Loc, Ty->getPointerTo());
      // FIXME: Pass alignment information down rather than just using 1 here.
      return Builder.CreateAlignedLoad(Loc, 1, "val");
    } else {
      // A value - just return it.
      assert(TheValue->getType() == Ty && "Value not of expected type!");
      return TheValue;
    }
  }

  void clear() {
    assert(LocStack.size() == 1 && "Imbalance!");
    LocStack.clear();
  }

  bool isShadowReturn() const { return isShadowRet; }
  bool isAggrReturn() { return isAggrRet; }

  // EmitShadowResult - If the return result was redirected to a buffer,
  // emit it now.
  Value *EmitShadowResult(tree type, const MemRef *DstLoc) {
    if (!RetBuf.Ptr)
      return 0;

    if (DstLoc) {
      // Copy out the aggregate return value now.
      assert(ConvertType(type) ==
             cast<PointerType>(RetBuf.Ptr->getType())->getElementType() &&
             "Inconsistent result types!");
      TheTreeToLLVM->EmitAggregateCopy(*DstLoc, RetBuf, type);
      return 0;
    } else {
      // Read out the scalar return value now.
      return Builder.CreateLoad(RetBuf.Ptr, "result");
    }
  }

  /// HandleScalarResult - This callback is invoked if the function returns a
  /// simple scalar result value.
  void HandleScalarResult(Type */*RetTy*/) {
    // There is nothing to do here if we return a scalar or void.
    assert(DestLoc == 0 &&
           "Call returns a scalar but caller expects aggregate!");
  }

  /// HandleAggregateResultAsScalar - This callback is invoked if the function
  /// returns an aggregate value by bit converting it to the specified scalar
  /// type and returning that.
  void HandleAggregateResultAsScalar(Type */*ScalarTy*/, unsigned Off = 0) {
    this->Offset = Off;
  }

  /// HandleAggregateResultAsAggregate - This callback is invoked if the
  /// function returns an aggregate value using multiple return values.
  void HandleAggregateResultAsAggregate(Type */*AggrTy*/) {
    // There is nothing to do here.
    isAggrRet = true;
  }

  /// HandleAggregateShadowResult - This callback is invoked if the function
  /// returns an aggregate value by using a "shadow" first parameter.  If
  /// RetPtr is set to true, the pointer argument itself is returned from the
  /// function.
  void HandleAggregateShadowResult(PointerType *PtrArgTy, bool /*RetPtr*/) {
    // We need to pass memory to write the return value into.
    // FIXME: alignment and volatility are being ignored!
    assert(!DestLoc || PtrArgTy == DestLoc->Ptr->getType());

    if (DestLoc == 0) {
      // The result is unused, but still needs to be stored somewhere.
      Value *Buf = TheTreeToLLVM->CreateTemporary(PtrArgTy->getElementType());
      CallOperands.push_back(Buf);
    } else if (useReturnSlot) {
      // Letting the call write directly to the final destination is safe and
      // may be required.  Do not use a buffer.
      CallOperands.push_back(DestLoc->Ptr);
    } else {
      // Letting the call write directly to the final destination may not be
      // safe (eg: if DestLoc aliases a parameter) and is not required - pass
      // a buffer and copy it to DestLoc after the call.
      RetBuf = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType());
      CallOperands.push_back(RetBuf.Ptr);
    }

    // Note the use of a shadow argument.
    isShadowRet = true;
  }

  void HandlePad(llvm::Type *LLVMTy) {
    CallOperands.push_back(UndefValue::get(LLVMTy));
  }

  /// HandleScalarShadowResult - This callback is invoked if the function
  /// returns a scalar value by using a "shadow" first parameter, which is a
  /// pointer to the scalar, of type PtrArgTy.  If RetPtr is set to true,
  /// the pointer argument itself is returned from the function.
  void HandleScalarShadowResult(PointerType *PtrArgTy, bool /*RetPtr*/) {
    assert(DestLoc == 0 &&
           "Call returns a scalar but caller expects aggregate!");
    // Create a buffer to hold the result.  The result will be loaded out of
    // it after the call.
    RetBuf = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType());
    CallOperands.push_back(RetBuf.Ptr);

    // Note the use of a shadow argument.
    isShadowRet = true;
  }

  /// HandleScalarArgument - This is the primary callback that specifies an
  /// LLVM argument to pass.  It is only used for first class types.
  void HandleScalarArgument(llvm::Type *LLVMTy, tree type,
                            unsigned RealSize = 0) {
    Value *Loc = NULL;
    if (RealSize) {
      Value *L = getAddress();
      Loc = LLVM_LOAD_SCALAR_ARGUMENT(L, LLVMTy, RealSize, Builder);
    } else
      Loc = getValue(LLVMTy);

    // Perform any implicit type conversions.
    if (CallOperands.size() < FTy->getNumParams()) {
      Type *CalledTy = FTy->getParamType(CallOperands.size());
      if (Loc->getType() != CalledTy) {
        if (type) {
          bool isSigned = !TYPE_UNSIGNED(type);
          Loc = TheTreeToLLVM->CastToAnyType(Loc, isSigned, CalledTy, false);
        } else {
          // Only trivial type conversions should get here.
          Loc = Builder.CreateBitCast(Loc, CalledTy);
        }
      }
    }

    CallOperands.push_back(Loc);
  }

  /// HandleByInvisibleReferenceArgument - This callback is invoked if a
  /// pointer (of type PtrTy) to the argument is passed rather than the
  /// argument itself.
  void HandleByInvisibleReferenceArgument(llvm::Type *PtrTy, tree /*type*/) {
    Value *Loc = getAddress();
    Loc = Builder.CreateBitCast(Loc, PtrTy);
    CallOperands.push_back(Loc);
  }

  /// HandleByValArgument - This callback is invoked if the aggregate function
  /// argument is passed by value. It is lowered to a parameter passed by
  /// reference with an additional parameter attribute "ByVal".
  void HandleByValArgument(llvm::Type *LLVMTy, tree /*type*/) {
    Value *Loc = getAddress();
    assert(LLVMTy->getPointerTo() == Loc->getType());
    (void) LLVMTy; // Otherwise unused if asserts off - avoid compiler warning.
    CallOperands.push_back(Loc);
  }

  /// HandleFCAArgument - This callback is invoked if the aggregate function
  /// argument is passed as a first class aggregate.
  void HandleFCAArgument(llvm::Type *LLVMTy, tree /*type*/) {
    Value *Loc = getAddress();
    assert(LLVMTy->getPointerTo() == Loc->getType());
    (void) LLVMTy; // Otherwise unused if asserts off - avoid compiler warning.
    CallOperands.push_back(Builder.CreateLoad(Loc));
  }

  /// EnterField - Called when we're about the enter the field of a struct
  /// or union.  FieldNo is the number of the element we are entering in the
  /// LLVM Struct, StructTy is the LLVM type of the struct we are entering.
  void EnterField(unsigned FieldNo, llvm::Type *StructTy) {
    Value *Loc = getAddress();
    Loc = Builder.CreateBitCast(Loc, StructTy->getPointerTo());
    pushAddress(
        Builder.CreateStructGEP(Loc, FieldNo, flag_verbose_asm ? "elt" : ""));
  }
  void ExitField() {
    assert(!LocStack.empty());
    LocStack.pop_back();
  }
};
}

/// EmitCallOf - Emit a call to the specified callee with the operands specified
/// in the GIMPLE_CALL 'stmt'. If the result of the call is a scalar, return the
/// result, otherwise store it in DestLoc.
Value *TreeToLLVM::EmitCallOf(Value *Callee, gimple stmt, const MemRef *DestLoc,
                              const AttributeSet &InPAL) {
  BasicBlock *LandingPad = 0; // Non-zero indicates an invoke.
  int LPadNo = 0;

  AttributeSet PAL = InPAL;
  if (PAL.isEmpty() && isa<Function>(Callee))
    PAL = cast<Function>(Callee)->getAttributes();

  // Work out whether to use an invoke or an ordinary call.
  if (!stmt_could_throw_p(stmt))
    // This call does not throw - mark it 'nounwind'.
    PAL = PAL.addAttribute(Callee->getContext(), AttributeSet::FunctionIndex,
                           Attribute::NoUnwind);

  if (!PAL.hasAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind)) {
    // This call may throw.  Determine if we need to generate
    // an invoke rather than a simple call.
    LPadNo = lookup_stmt_eh_lp(stmt);

    if (LPadNo > 0) {
      // The call is in an exception handling region with a landing pad.
      // Generate an invoke, with the GCC landing pad as the unwind destination.
      // The destination may change to an LLVM only landing pad,  which precedes
      // the GCC one, after phi nodes have been populated (doing things this way
      // simplifies the generation of phi nodes).
      eh_landing_pad lp = get_eh_landing_pad_from_number(LPadNo);
      assert(lp && "Post landing pad not found!");
      LandingPad = getLabelDeclBlock(lp->post_landing_pad);
    } else if (LPadNo < 0) {
      eh_region region = get_eh_region_from_lp_number(LPadNo);
      // The call is in a must-not-throw region.  Generate an invoke that causes
      // the region's failure code to be run if an exception is thrown.
      assert(region->type == ERT_MUST_NOT_THROW && "Unexpected region type!");

      // Unwind to the block containing the failure code.
      LandingPad = getFailureBlock(region->index);
    }
  }

  tree fndecl = gimple_call_fndecl(stmt);
#if (GCC_MINOR < 7)
  tree fntype =
      fndecl ? TREE_TYPE(fndecl) : TREE_TYPE(TREE_TYPE(gimple_call_fn(stmt)));
#else
  tree fntype = gimple_call_fntype(stmt);
#endif

  // Determine the calling convention.
  CallingConv::ID CallingConvention = CallingConv::C;
#ifdef TARGET_ADJUST_LLVM_CC
  TARGET_ADJUST_LLVM_CC(CallingConvention, fntype);
#endif

  SmallVector<Value *, 16> CallOperands;
  PointerType *PFTy = cast<PointerType>(Callee->getType());
  FunctionType *FTy = cast<FunctionType>(PFTy->getElementType());
  FunctionCallArgumentConversion Client(CallOperands, FTy, DestLoc,
                                        gimple_call_return_slot_opt_p(stmt),
                                        Builder, CallingConvention);
  DefaultABI ABIConverter(Client);

  // Handle the result, including struct returns.
  ABIConverter.HandleReturnType(gimple_call_return_type(stmt),
                                fndecl ? fndecl : fntype,
                                fndecl ? DECL_BUILT_IN(fndecl) : false);

  // Pass the static chain, if any, as the first parameter.
  if (gimple_call_chain(stmt))
    CallOperands.push_back(EmitMemory(gimple_call_chain(stmt)));

  // Loop over the arguments, expanding them and adding them to the op list.
  std::vector<Type *> ScalarArgs;
  for (unsigned i = 0, e = gimple_call_num_args(stmt); i != e; ++i) {
    tree arg = gimple_call_arg(stmt, i);
    tree type = TREE_TYPE(arg);
    Type *ArgTy = ConvertType(type);

    // Push the argument.
    if (ArgTy->isSingleValueType()) {
      // A scalar - push the value.
      Client.pushValue(EmitMemory(arg));
    } else if (LLVM_SHOULD_PASS_AGGREGATE_AS_FCA(type, ArgTy)) {
      if (isa<AGGREGATE_TYPE>(type)) {
        // Pass the aggregate as a first class value.
        LValue ArgVal = EmitLV(arg);
        Client.pushValue(Builder.CreateLoad(ArgVal.Ptr));
      } else {
        // Already first class (eg: a complex number) - push the value.
        Client.pushValue(EmitMemory(arg));
      }
    } else {
      if (isa<AGGREGATE_TYPE>(type)) {
        // An aggregate - push the address.
        LValue ArgVal = EmitLV(arg);
        assert(!ArgVal.isBitfield() && "Bitfields are first-class types!");
        Client.pushAddress(ArgVal.Ptr);
      } else {
        // A first class value (eg: a complex number).  Push the address of a
        // temporary copy.
        MemRef Copy = CreateTempLoc(ArgTy);
        StoreRegisterToMemory(EmitRegister(arg), Copy, type, 0, Builder);
        Client.pushAddress(Copy.Ptr);
      }
    }

    AttrBuilder AttrBuilder;

    unsigned OldSize = CallOperands.size();

    ABIConverter.HandleArgument(type, ScalarArgs, &AttrBuilder);

    if (AttrBuilder.hasAttributes()) {
      // If the argument is split into multiple scalars, assign the
      // attributes to all scalars of the aggregate.
      for (unsigned j = OldSize + 1; j <= CallOperands.size(); ++j)
        PAL = PAL.addAttributes(Context, j,
                                AttributeSet::get(Context, j, AttrBuilder));
    }

    Client.clear();
  }

  // If the caller and callee disagree about a parameter type but the difference
  // is trivial, correct the type used by the caller.
  for (unsigned i = 0, e = std::min((unsigned) CallOperands.size(),
                                    FTy->getNumParams());
       i != e; ++i) {
    Type *ExpectedTy = FTy->getParamType(i);
    Type *ActualTy = CallOperands[i]->getType();
    if (ActualTy == ExpectedTy)
      continue;
    assert(isa<PointerType>(ActualTy) && isa<PointerType>(ExpectedTy) &&
           "Type difference is not trivial!");
    CallOperands[i] = Builder.CreateBitCast(CallOperands[i], ExpectedTy);
  }

  // Unlike LLVM, GCC does not require that call statements provide a value for
  // every function argument (it passes rubbish for arguments with no value).
  // To get the same effect we pass 'undef' for any unspecified arguments.
  if (CallOperands.size() < FTy->getNumParams())
    for (unsigned i = CallOperands.size(), e = FTy->getNumParams(); i != e; ++i)
      CallOperands.push_back(UndefValue::get(FTy->getParamType(i)));

  Value *Call;
  if (!LandingPad) {
    Call = Builder.CreateCall(Callee, CallOperands);
    cast<CallInst>(Call)->setCallingConv(CallingConvention);
    cast<CallInst>(Call)->setAttributes(PAL);
  } else {
    BasicBlock *NextBlock = BasicBlock::Create(Context);
    Call = Builder.CreateInvoke(Callee, NextBlock, LandingPad, CallOperands);
    cast<InvokeInst>(Call)->setCallingConv(CallingConvention);
    cast<InvokeInst>(Call)->setAttributes(PAL);

    if (LPadNo > 0) {
      // The invoke's destination may change to an LLVM only landing pad, which
      // precedes the GCC one, after phi nodes have been populated (doing things
      // this way simplifies the generation of phi nodes).  Record the invoke as
      // well as the GCC exception handling region.
      if ((unsigned) LPadNo >= NormalInvokes.size())
        NormalInvokes.resize(LPadNo + 1);
      NormalInvokes[LPadNo].push_back(cast<InvokeInst>(Call));
    }

    BeginBlock(NextBlock);
  }

  // If the call statement has void type then either the callee does not return
  // a result, or it does but the result should be discarded.
  if (isa<VOID_TYPE>(gimple_call_return_type(stmt)))
    return 0;

  if (Client.isShadowReturn())
    return Client.EmitShadowResult(gimple_call_return_type(stmt), DestLoc);

  if (Client.isAggrReturn()) {
    MemRef Target;
    if (DestLoc)
      Target = *DestLoc;
    else
      // Destination is a first class value (eg: a complex number).  Extract to
      // a temporary then load the value out later.
      Target = CreateTempLoc(ConvertType(gimple_call_return_type(stmt)));

    if (DL.getTypeAllocSize(Call->getType()) <=
        DL.getTypeAllocSize(cast<PointerType>(Target.Ptr->getType())
                                ->getElementType())) {
      Value *Dest =
          Builder.CreateBitCast(Target.Ptr, Call->getType()->getPointerTo());
      LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call, Dest, Target.Volatile, Builder);
    } else {
      // The call will return an aggregate value in registers, but
      // those registers are bigger than Target.  Allocate a
      // temporary to match the registers, store the registers there,
      // cast the temporary into the correct (smaller) type, and using
      // the correct type, copy the value into Target.  Assume the
      // optimizer will delete the temporary and clean this up.
      AllocaInst *biggerTmp = CreateTemporary(Call->getType());
      LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call, biggerTmp, /*Volatile=*/ false,
                                         Builder);
      EmitAggregateCopy(
          Target, MemRef(Builder.CreateBitCast(biggerTmp,
                                               Call->getType()->getPointerTo()),
                         Target.getAlignment(), Target.Volatile),
          gimple_call_return_type(stmt));
    }

    return DestLoc ? 0 : Builder.CreateLoad(Target.Ptr);
  }

  if (!DestLoc) {
    Type *RetTy = ConvertType(gimple_call_return_type(stmt));
    if (Call->getType() == RetTy)
      return Call; // Normal scalar return.

    // May be something as simple as a float being returned as an integer, or
    // something trickier like a complex int type { i32, i32 } being returned
    // as an i64.
    if (Call->getType()->canLosslesslyBitCastTo(RetTy))
      return Builder.CreateBitCast(Call, RetTy); // Simple case.
    // Probably a scalar to complex conversion.
    assert(DL.getTypeAllocSize(Call->getType()) == DL.getTypeAllocSize(RetTy) &&
           "Size mismatch in scalar to scalar conversion!");
    Value *Tmp = CreateTemporary(Call->getType());
    Builder.CreateStore(Call, Tmp);
    return Builder.CreateLoad(
        Builder.CreateBitCast(Tmp, RetTy->getPointerTo()));
  }

  // If the caller expects an aggregate, we have a situation where the ABI for
  // the current target specifies that the aggregate be returned in scalar
  // registers even though it is an aggregate.  We must bitconvert the scalar
  // to the destination aggregate type.  We do this by casting the DestLoc
  // pointer and storing into it.  The store does not necessarily start at the
  // beginning of the aggregate (x86-64).
  Value *Ptr = DestLoc->Ptr;
  unsigned Align = DestLoc->getAlignment();
  // AggTy - The type of the aggregate being stored to.
  Type *AggTy = cast<PointerType>(Ptr->getType())->getElementType();
  // MaxStoreSize - The maximum number of bytes we can store without overflowing
  // the aggregate.
  int64_t MaxStoreSize = DL.getTypeAllocSize(AggTy);
  if (Client.Offset) {
    Ptr = Builder.CreateBitCast(Ptr, Type::getInt8PtrTy(Context));
    Ptr = Builder.CreateGEP(
        Ptr, ConstantInt::get(DL.getIntPtrType(Ptr->getType()), Client.Offset),
        flag_verbose_asm ? "ro" : "");
    Align = MinAlign(Align, Client.Offset);
    MaxStoreSize -= Client.Offset;
  }
  assert(MaxStoreSize > 0 && "Storing off end of aggregate?");
  Value *Val = Call;
  // Check whether storing the scalar directly would overflow the aggregate.
  if (DL.getTypeStoreSize(Call->getType()) > (uint64_t) MaxStoreSize) {
    // Chop down the size of the scalar to the maximum number of bytes that can
    // be stored without overflowing the destination.
    // TODO: Check whether this works correctly on big-endian machines.
    // Store the scalar to a temporary.
    Value *Tmp = CreateTemporary(Call->getType());
    Builder.CreateStore(Call, Tmp);
    // Load the desired number of bytes back out again as an integer of the
    // appropriate size.
    Type *SmallTy = IntegerType::get(Context, MaxStoreSize * 8);
    Tmp = Builder.CreateBitCast(Tmp, PointerType::getUnqual(SmallTy));
    Val = Builder.CreateLoad(Tmp);
    // Store the integer rather than the call result to the aggregate.
  }
  Ptr = Builder.CreateBitCast(Ptr, PointerType::getUnqual(Val->getType()));
  Builder.CreateAlignedStore(Val, Ptr, Align, DestLoc->Volatile);
  return 0;
}

/// EmitSimpleCall - Emit a call to the function with the given name and return
/// type, passing the provided arguments (which should all be gimple registers
/// or local constants of register type).  No marshalling is done: the arguments
/// are directly passed through.
CallInst *TreeToLLVM::EmitSimpleCall(StringRef CalleeName, tree ret_type,
                                     /* arguments */ ...) {
  va_list ops;
  va_start(ops, ret_type);

  // Build the list of arguments.
  std::vector<Value *> Args;
#ifdef TARGET_ADJUST_LLVM_CC
  // Build the list of GCC argument types.
  tree arg_types;
  tree *chainp = &arg_types;
#endif
  while (tree arg = va_arg(ops, tree)) {
    Args.push_back(EmitRegister(arg));
#ifdef TARGET_ADJUST_LLVM_CC
    *chainp = build_tree_list(NULL, TREE_TYPE(arg));
    chainp = &TREE_CHAIN(*chainp);
#endif
  }
#ifdef TARGET_ADJUST_LLVM_CC
  // Indicate that this function is not varargs.
  *chainp = void_list_node;
#endif
  va_end(ops);

  Type *RetTy = isa<VOID_TYPE>(ret_type) ? Type::getVoidTy(Context)
                                         : getRegType(ret_type);

  // The LLVM argument types.
  std::vector<Type *> ArgTys;
  ArgTys.reserve(Args.size());
  for (unsigned i = 0, e = Args.size(); i != e; ++i)
    ArgTys.push_back(Args[i]->getType());

  // Determine the calling convention.
  CallingConv::ID CC = CallingConv::C;
#ifdef TARGET_ADJUST_LLVM_CC
  // Query the target for the calling convention to use.
  tree fntype = build_function_type(ret_type, arg_types);
  TARGET_ADJUST_LLVM_CC(CC, fntype);
#endif

  // Get the function declaration for the callee.
  FunctionType *FTy = FunctionType::get(RetTy, ArgTys, /*isVarArg*/ false);
  Constant *Func = TheModule->getOrInsertFunction(CalleeName, FTy);

  // If the function already existed with the wrong prototype then don't try to
  // muck with its calling convention.  Otherwise, set the calling convention.
  if (Function *F = llvm::dyn_cast<Function>(Func))
    F->setCallingConv(CC);

  // Finally, call the function.
  CallInst *CI = Builder.CreateCall(Func, Args);
  CI->setCallingConv(CC);
  return CI;
}

//===----------------------------------------------------------------------===//
//               ... Inline Assembly and Register Variables ...
//===----------------------------------------------------------------------===//

// LLVM_GET_REG_NAME - Default to use GCC's register names.  Targets may
// override this to use different names for some registers.  The REG_NAME is
// the name before it was decoded; it may be null in some contexts.
#ifndef LLVM_GET_REG_NAME
#define LLVM_GET_REG_NAME(REG_NAME, REG_NUM) reg_names[REG_NUM]
#endif

// LLVM_CANONICAL_ADDRESS_CONSTRAINTS - GCC defines the "p" constraint to
// allow a valid memory address, but targets differ widely on what is allowed
// as an address.  This macro is a string containing the canonical constraint
// characters that are conservatively valid addresses.  Default to allowing an
// address in a register, since that works for many targets.
#ifndef LLVM_CANONICAL_ADDRESS_CONSTRAINTS
#define LLVM_CANONICAL_ADDRESS_CONSTRAINTS "r"
#endif

/// Reads from register variables are handled by emitting an inline asm node
/// that copies the value out of the specified register.
Value *TreeToLLVM::EmitReadOfRegisterVariable(tree decl) {
  Type *MemTy = ConvertType(TREE_TYPE(decl));
  Type *RegTy = getRegType(TREE_TYPE(decl));

  // If there was an error, return something bogus.
  if (ValidateRegisterVariable(decl))
    return UndefValue::get(RegTy);

  // Turn this into a 'tmp = call Ty asm "", "={reg}"()'.
  FunctionType *FTy = FunctionType::get(MemTy, std::vector<Type *>(), false);

  const char *Name = extractRegisterName(decl);
  Name = LLVM_GET_REG_NAME(Name, decode_reg_name(Name));

  InlineAsm *IA = InlineAsm::get(FTy, "", "={" + std::string(Name) + "}", true);
  CallInst *Call = Builder.CreateCall(IA);
  Call->setDoesNotThrow();

  // Convert the call result to in-register type.
  return Mem2Reg(Call, TREE_TYPE(decl), Builder);
}

/// Stores to register variables are handled by emitting an inline asm node
/// that copies the value into the specified register.
void TreeToLLVM::EmitModifyOfRegisterVariable(tree decl, Value *RHS) {
  // If there was an error, bail out.
  if (ValidateRegisterVariable(decl))
    return;

  // Convert to in-memory type.
  RHS = Reg2Mem(RHS, TREE_TYPE(decl), Builder);

  // Turn this into a 'call void asm sideeffect "", "{reg}"(Ty %RHS)'.
  std::vector<Type *> ArgTys;
  ArgTys.push_back(RHS->getType());
  FunctionType *FTy =
      FunctionType::get(Type::getVoidTy(Context), ArgTys, false);

  const char *Name = extractRegisterName(decl);
  Name = LLVM_GET_REG_NAME(Name, decode_reg_name(Name));

  InlineAsm *IA = InlineAsm::get(FTy, "", "{" + std::string(Name) + "}", true);
  CallInst *Call = Builder.CreateCall(IA, RHS);
  Call->setDoesNotThrow();
}

/// ConvertInlineAsmStr - Convert the specified inline asm string to an LLVM
/// InlineAsm string.  The GNU style inline asm template string has the
/// following format:
///   %N (for N a digit) means print operand N in usual manner.
///   %=  means a unique number for the inline asm.
///   %lN means require operand N to be a CODE_LABEL or LABEL_REF
///       and print the label name with no punctuation.
///   %cN means require operand N to be a constant
///       and print the constant expression with no punctuation.
///   %aN means expect operand N to be a memory address
///       (not a memory reference!) and print a reference to that address.
///   %nN means expect operand N to be a constant and print a constant
///       expression for minus the value of the operand, with no other
///       punctuation.
/// Other %xN expressions are turned into LLVM ${N:x} operands.
///
static std::string ConvertInlineAsmStr(gimple stmt, unsigned NumOperands) {
  const char *AsmStr = gimple_asm_string(stmt);

  // gimple_asm_input_p - This flag is set if this is a non-extended ASM,
  // which means that the asm string should not be interpreted, other than
  // to escape $'s.
  if (gimple_asm_input_p(stmt)) {
    const char *InStr = AsmStr;
    std::string Result;
    while (1) {
      switch (*InStr++) {
      case 0:
        return Result; // End of string.
      default:
        Result += InStr[-1];
        break; // Normal character.
      case '$':
        Result += "$$";
        break; // Escape '$' characters.
      }
    }
  }

  std::string Result;
  while (1) {
    switch (*AsmStr++) {
    case 0:
      return Result; // End of string.
    default:
      Result += AsmStr[-1];
      break; // Normal character.
    case '$':
      Result += "$$";
      break; // Escape '$' characters.
#ifdef ASSEMBLER_DIALECT
      // Note that we can't escape to ${, because that is the syntax for vars.
    case '{':
      Result += "$(";
      break; // Escape '{' character.
    case '}':
      Result += "$)";
      break; // Escape '}' character.
    case '|':
      Result += "$|";
      break; // Escape '|' character.
#endif
    case '%': // GCC escape character.
      char EscapedChar = *AsmStr++;
      if (EscapedChar == '%') { // Escaped '%' character
        Result += '%';
      } else if (EscapedChar == '=') { // Unique ID for the asm instance.
        Result += "${:uid}";
      }
#ifdef LLVM_ASM_EXTENSIONS
      LLVM_ASM_EXTENSIONS(EscapedChar, AsmStr, Result)
#endif
          else if (ISALPHA(EscapedChar)) {
        // % followed by a letter and some digits. This outputs an operand in a
        // special way depending on the letter.  We turn this into LLVM ${N:o}
        // syntax.
        char *EndPtr;
        unsigned long OpNum = strtoul(AsmStr, &EndPtr, 10);

        if (AsmStr == EndPtr) {
          error("operand number missing after %%-letter");
          return Result;
        } else if (OpNum >= NumOperands) {
          error("operand number out of range");
          return Result;
        }
        Result += "${" + utostr(OpNum) + ":" + EscapedChar + "}";
        AsmStr = EndPtr;
      }
      else if (ISDIGIT(EscapedChar)) {
        char *EndPtr;
        unsigned long OpNum = strtoul(AsmStr - 1, &EndPtr, 10);
        AsmStr = EndPtr;
        Result += "$" + utostr(OpNum);
#ifdef PRINT_OPERAND_PUNCT_VALID_P
      }
      else if (PRINT_OPERAND_PUNCT_VALID_P((unsigned char) EscapedChar)) {
        Result += "${:";
        Result += EscapedChar;
        Result += "}";
#endif
      }
      else {
        output_operand_lossage("invalid %%-code");
      }
      break;
    }
  }
}

/// isOperandMentioned - Return true if the given operand is explicitly
/// mentioned in the asm string.  For example if passed operand 1 then
/// this routine checks that the asm string does not contain "%1".
static bool isOperandMentioned(gimple stmt, unsigned OpNum) {
  // If this is a non-extended ASM then the contents of the asm string are not
  // to be interpreted.
  if (gimple_asm_input_p(stmt))
    return false;
  // Search for a non-escaped '%' character followed by OpNum.
  for (const char *AsmStr = gimple_asm_string(stmt); * AsmStr; ++AsmStr) {
    if (*AsmStr != '%')
      // Not a '%', move on to next character.
      continue;
    char Next = AsmStr[1];
    // If this is "%%" then the '%' is escaped - skip both '%' characters.
    if (Next == '%') {
      ++AsmStr;
      continue;
    }
    // Whitespace is not allowed between the '%' and the number, so check that
    // the next character is a digit.
    if (!ISDIGIT(Next))
      continue;
    char *EndPtr;
    // If this is an explicit reference to OpNum then we are done.
    if (OpNum == strtoul(AsmStr + 1, &EndPtr, 10))
      return true;
    // Otherwise, skip over the number and keep scanning.
    AsmStr = EndPtr - 1;
  }
  return false;
}

/// CanonicalizeConstraint - If we can canonicalize the constraint into
/// something simpler, do so now.  This turns register classes with a single
/// register into the register itself, expands builtin constraints to multiple
/// alternatives, etc.
static std::string CanonicalizeConstraint(const char *Constraint) {
  std::string Result;

  // Skip over modifier characters.
  bool DoneModifiers = false;
  while (!DoneModifiers) {
    switch (*Constraint) {
    default:
      DoneModifiers = true;
      break;
    case '=':
      llvm_unreachable("Should be after '='s");
    case '+':
      llvm_unreachable("'+' should already be expanded");
    case '*':
    case '?':
    case '!':
      ++Constraint;
      break;
    case '&': // Pass earlyclobber to LLVM.
    case '%': // Pass commutative to LLVM.
      Result += *Constraint++;
      break;
    case '#': // No constraint letters left.
      return Result;
    }
  }

  // If this constraint is multiple letters add a parsing helper prefix.
  if (CONSTRAINT_LEN(*Constraint, Constraint) > 1)
    Result += "^";

  while (*Constraint) {
    char ConstraintChar = *Constraint++;

    // 'g' is just short-hand for 'imr'.
    if (ConstraintChar == 'g') {
      Result += "imr";
      continue;
    }

    // Translate 'p' to a target-specific set of constraints that
    // conservatively allow a valid memory address.  For inline assembly there
    // is no way to know the mode of the data being addressed, so this is only
    // a rough approximation of how GCC handles this constraint.
    if (ConstraintChar == 'p') {
      Result += LLVM_CANONICAL_ADDRESS_CONSTRAINTS;
      continue;
    }

    // See if this is a regclass constraint.
    unsigned RegClass;
    if (ConstraintChar == 'r')
      // REG_CLASS_FROM_CONSTRAINT doesn't support 'r' for some reason.
      RegClass = GENERAL_REGS;
    else
      RegClass = REG_CLASS_FROM_CONSTRAINT(Constraint[-1], Constraint - 1);

    if (RegClass == NO_REGS) { // not a reg class.
      Result += ConstraintChar;
      continue;
    }

    // Look to see if the specified regclass has exactly one member, and if so,
    // what it is.  Cache this information in AnalyzedRegClasses once computed.
    static std::map<unsigned, int> AnalyzedRegClasses;

    std::map<unsigned, int>::iterator I =
        AnalyzedRegClasses.lower_bound(RegClass);

    int RegMember;
    if (I != AnalyzedRegClasses.end() && I->first == RegClass) {
      // We've already computed this, reuse value.
      RegMember = I->second;
    } else {
      // Otherwise, scan the regclass, looking for exactly one member.
      RegMember = -1; // -1 => not a single-register class.
      for (unsigned j = 0; j != FIRST_PSEUDO_REGISTER; ++j)
        if (TEST_HARD_REG_BIT(reg_class_contents[RegClass], j)) {
          if (RegMember == -1) {
            RegMember = j;
          } else {
            RegMember = -1;
            break;
          }
        }
      // Remember this answer for the next query of this regclass.
      AnalyzedRegClasses.insert(I, std::make_pair(RegClass, RegMember));
    }

    // If we found a single register register class, return the register.
    if (RegMember != -1) {
      Result += '{';
      Result += LLVM_GET_REG_NAME(0, RegMember);
      Result += '}';
    } else {
      Result += ConstraintChar;
    }
  }

  return Result;
}

/// See if operand "exp" can use the indicated Constraint (which is
/// terminated by a null or a comma).
/// Returns:  -1=no, 0=yes but auxiliary instructions needed, 1=yes and free
static int MatchWeight(const char *Constraint, tree Operand) {
  const char *p = Constraint;
  int RetVal = 0;
  // Look for hard register operand.  This matches only a constraint of a
  // register class that includes that hard register, and it matches that
  // perfectly, so we never return 0 in this case.
  if (isa<VAR_DECL>(Operand) && DECL_HARD_REGISTER(Operand)) {
    int RegNum = decode_reg_name(extractRegisterName(Operand));
    RetVal = -1;
    if (RegNum >= 0) {
      do {
        unsigned RegClass;
        if (*p == 'r')
          RegClass = GENERAL_REGS;
        else
          RegClass = REG_CLASS_FROM_CONSTRAINT(*p, p);
        if (RegClass != NO_REGS &&
            TEST_HARD_REG_BIT(reg_class_contents[RegClass], RegNum)) {
          RetVal = 1;
          break;
        }
        ++p;
      } while (*p != ',' && *p != 0);
    }
  }
  // Look for integer constant operand.  This cannot match "m", and "i" is
  // better than "r".  FIXME target-dependent immediate letters are not handled
  // yet; in general they require looking at the value.
  if (isa<INTEGER_CST>(Operand)) {
    do {
      RetVal = -1;
      if (*p == 'i' || *p == 'n') { // integer constant
        RetVal = 1;
        break;
      }
      if (*p != 'm' && *p != 'o' && *p != 'V') // not memory
        RetVal = 0;
      ++p;
    } while (*p != ',' && *p != 0);
  }
  /// TEMPORARY.  This has the effect that alternative 0 is always chosen,
  /// except in the cases handled above.
  return RetVal;
}

/// ChooseConstraintTuple: we know each of the NumInputs+NumOutputs strings
/// in Constraints[] is a comma-separated list of NumChoices different
/// constraints.  Look through the operands and constraint possibilities
/// and pick a tuple where all the operands match.  Replace the strings
/// in Constraints[] with the shorter strings from that tuple (malloc'ed,
/// caller is responsible for cleaning it up).  Later processing can alter what
/// Constraints points to, so to make sure we delete everything, the addresses
/// of everything we allocated also are returned in StringStorage.
/// Casting back and forth from char* to const char* is Ugly, but we have to
/// interface with C code that expects const char*.
///
/// gcc's algorithm for picking "the best" tuple is quite complicated, and
/// is performed after things like SROA, not before.  At the moment we are
/// just trying to pick one that will work.  This may get refined.
static void ChooseConstraintTuple(gimple stmt, const char **Constraints,
                                  unsigned NumChoices,
                                  BumpPtrAllocator &StringStorage) {
  unsigned NumInputs = gimple_asm_ninputs(stmt);
  unsigned NumOutputs = gimple_asm_noutputs(stmt);

  int MaxWeight = -1;
  unsigned int CommasToSkip = 0;
  int *Weights = (int *)alloca(NumChoices * sizeof(int));
  // RunningConstraints is pointers into the Constraints strings which
  // are incremented as we go to point to the beginning of each
  // comma-separated alternative.
  const char **RunningConstraints =
      (const char **)alloca((NumInputs + NumOutputs) * sizeof(const char *));
  memcpy(RunningConstraints, Constraints,
         (NumInputs + NumOutputs) * sizeof(const char *));
  // The entire point of this loop is to compute CommasToSkip.
  for (unsigned i = 0; i != NumChoices; ++i) {
    Weights[i] = 0;
    for (unsigned j = 0; j != NumOutputs; ++j) {
      tree Output = gimple_asm_output_op(stmt, j);
      if (i == 0)
        RunningConstraints[j]++; // skip leading =
      const char *p = RunningConstraints[j];
      while (*p == '*' || *p == '&' || *p == '%') // skip modifiers
        p++;
      if (Weights[i] != -1) {
        int w = MatchWeight(p, TREE_VALUE(Output));
        // Nonmatch means the entire tuple doesn't match.  However, we
        // keep scanning to set up RunningConstraints correctly for the
        // next tuple.
        if (w < 0)
          Weights[i] = -1;
        else
          Weights[i] += w;
      }
      while (*p != 0 && *p != ',')
        p++;
      if (*p != 0) {
        p++; // skip comma
        while (*p == '*' || *p == '&' || *p == '%')
          p++; // skip modifiers
      }
      RunningConstraints[j] = p;
    }
    for (unsigned j = 0; j != NumInputs; ++j) {
      tree Input = gimple_asm_input_op(stmt, j);
      const char *p = RunningConstraints[NumOutputs + j];
      if (Weights[i] != -1) {
        int w = MatchWeight(p, TREE_VALUE(Input));
        if (w < 0)
          Weights[i] = -1; // As above.
        else
          Weights[i] += w;
      }
      while (*p != 0 && *p != ',')
        p++;
      if (*p != 0)
        p++;
      RunningConstraints[NumOutputs + j] = p;
    }
    if (Weights[i] > MaxWeight) {
      CommasToSkip = i;
      MaxWeight = Weights[i];
    }
  }
  // We have picked an alternative (the CommasToSkip'th one).
  // Change Constraints to point to malloc'd copies of the appropriate
  // constraints picked out of the original strings.
  for (unsigned int i = 0; i < NumInputs + NumOutputs; i++) {
    assert(*(RunningConstraints[i]) == 0); // sanity check
    const char *start = Constraints[i];
    if (i < NumOutputs)
      start++; // skip '=' or '+'
    const char *end = start;
    while (*end != ',' && *end != 0)
      end++;
    for (unsigned int j = 0; j < CommasToSkip; j++) {
      start = end + 1;
      end = start;
      while (*end != ',' && *end != 0)
        end++;
    }
    // String we want is at start..end-1 inclusive.
    // For outputs, copy the leading = or +.
    char *newstring;
    if (i < NumOutputs) {
      newstring = StringStorage.Allocate<char>(end - start + 1 + 1);
      newstring[0] = *(Constraints[i]);
      strncpy(newstring + 1, start, end - start);
      newstring[end - start + 1] = 0;
    } else {
      newstring = StringStorage.Allocate<char>(end - start + 1);
      strncpy(newstring, start, end - start);
      newstring[end - start] = 0;
    }
    Constraints[i] = (const char *)newstring;
  }
}

//===----------------------------------------------------------------------===//
//               ... Helpers for Builtin Function Expansion ...
//===----------------------------------------------------------------------===//

Value *TreeToLLVM::BuildVector(const std::vector<Value *> &Ops) {
  assert((Ops.size() & (Ops.size() - 1)) == 0 &&
         "Not a power-of-two sized vector!");
  bool AllConstants = true;
  for (unsigned i = 0, e = Ops.size(); i != e && AllConstants; ++i)
    AllConstants &= isa<Constant>(Ops[i]);

  // If this is a constant vector, create a ConstantVector.
  if (AllConstants) {
    SmallVector<Constant *, 16> CstOps;
    for (unsigned i = 0, e = Ops.size(); i != e; ++i)
      CstOps.push_back(cast<Constant>(Ops[i]));
    return ConstantVector::get(CstOps);
  }

  // Otherwise, insertelement the values to build the vector.
  Value *Result =
      UndefValue::get(VectorType::get(Ops[0]->getType(), Ops.size()));

  for (unsigned i = 0, e = Ops.size(); i != e; ++i)
    Result = Builder.CreateInsertElement(Result, Ops[i], Builder.getInt32(i));

  return Result;
}

/// BuildVector - This varargs function builds a literal vector ({} syntax) with
/// the specified null-terminated list of elements.  The elements must be all
/// the same element type and there must be a power of two of them.
Value *TreeToLLVM::BuildVector(Value *Elt, ...) {
  std::vector<Value *> Ops;
  va_list VA;
  va_start(VA, Elt);

  Ops.push_back(Elt);
  while (Value *Arg = va_arg(VA, Value *))
    Ops.push_back(Arg);
  va_end(VA);

  return BuildVector(Ops);
}

/// BuildVectorShuffle - Given two vectors and a variable length list of int
/// constants, create a shuffle of the elements of the inputs, where each dest
/// is specified by the indexes.  The int constant list must be as long as the
/// number of elements in the input vector.
///
/// Undef values may be specified by passing in -1 as the result value.
///
Value *TreeToLLVM::BuildVectorShuffle(Value *InVec1, Value *InVec2, ...) {
  assert(InVec1->getType()->isVectorTy() &&
         InVec1->getType() == InVec2->getType() && "Invalid shuffle!");
  unsigned NumElements = cast<VectorType>(InVec1->getType())->getNumElements();

  // Get all the indexes from varargs.
  SmallVector<Constant *, 16> Idxs;
  va_list VA;
  va_start(VA, InVec2);
  for (unsigned i = 0; i != NumElements; ++i) {
    int idx = va_arg(VA, int);
    if (idx == -1)
      Idxs.push_back(UndefValue::get(Type::getInt32Ty(Context)));
    else {
      assert((unsigned) idx < 2 * NumElements && "Element index out of range!");
      Idxs.push_back(Builder.getInt32(idx));
    }
  }
  va_end(VA);

  // Turn this into the appropriate shuffle operation.
  return Builder.CreateShuffleVector(InVec1, InVec2, ConstantVector::get(Idxs));
}

//===----------------------------------------------------------------------===//
//                     ... Builtin Function Expansion ...
//===----------------------------------------------------------------------===//

/// EmitFrontendExpandedBuiltinCall - We allow the target to do some amount
/// of lowering.  This allows us to avoid having intrinsics for operations that
/// directly correspond to LLVM constructs.
///
/// This method returns true if the builtin is handled, otherwise false.
///
bool TreeToLLVM::EmitFrontendExpandedBuiltinCall(
    gimple stmt, tree fndecl, const MemRef *DestLoc, Value *&Result) {
#ifdef LLVM_TARGET_INTRINSIC_LOWER
  // Get the result type and operand line in an easy to consume format.
  Type *ResultType = ConvertType(TREE_TYPE(TREE_TYPE(fndecl)));
  std::vector<Value *> Operands;
  for (unsigned i = 0, e = gimple_call_num_args(stmt); i != e; ++i) {
    tree OpVal = gimple_call_arg(stmt, i);
    if (isa<AGGREGATE_TYPE>(TREE_TYPE(OpVal))) {
      MemRef OpLoc = CreateTempLoc(ConvertType(TREE_TYPE(OpVal)));
      EmitAggregate(OpVal, OpLoc);
      Operands.push_back(Builder.CreateLoad(OpLoc.Ptr));
    } else {
      Operands.push_back(EmitMemory(OpVal));
    }
  }

  return LLVM_TARGET_INTRINSIC_LOWER(stmt, fndecl, DestLoc, Result, ResultType,
                                     Operands);
#else
  // Avoid compiler warnings about unused parameters.
  (void) stmt;
  (void) fndecl;
  (void) DestLoc;
  (void) Result;
  return false;
#endif
}

/// TargetBuiltinCache - A cache of builtin intrinsics indexed by the GCC
/// builtin number.
static std::vector<Constant *> TargetBuiltinCache;

Value *TreeToLLVM::BuildBinaryAtomic(gimple stmt, AtomicRMWInst::BinOp Kind,
                                     unsigned PostOp) {
  tree return_type = gimple_call_return_type(stmt);
  Type *ResultTy = ConvertType(return_type);
  Value *C[2] = { EmitMemory(gimple_call_arg(stmt, 0)),
                  EmitMemory(gimple_call_arg(stmt, 1)) };
  Type *Ty[2];
  Ty[0] = ResultTy;
  Ty[1] = ResultTy->getPointerTo();
  C[0] = Builder.CreateBitCast(C[0], Ty[1]);
  C[1] = Builder.CreateIntCast(
      C[1], Ty[0], /*isSigned*/ !TYPE_UNSIGNED(return_type), "cast");
  Value *Result =
      Builder.CreateAtomicRMW(Kind, C[0], C[1], SequentiallyConsistent);
  if (PostOp)
    Result = Builder.CreateBinOp(Instruction::BinaryOps(PostOp), Result, C[1]);

  Result = Builder.CreateIntToPtr(Result, ResultTy);
  return Result;
}

Value *
TreeToLLVM::BuildCmpAndSwapAtomic(gimple stmt, unsigned Bits, bool isBool) {
  tree ptr = gimple_call_arg(stmt, 0);
  tree old_val = gimple_call_arg(stmt, 1);
  tree new_val = gimple_call_arg(stmt, 2);

  // The type loaded from/stored to memory.
  Type *MemTy = IntegerType::get(Context, Bits);
  Type *MemPtrTy = MemTy->getPointerTo();

  Value *Ptr = Builder.CreateBitCast(EmitRegister(ptr), MemPtrTy);
  Value *Old_Val =
      CastToAnyType(EmitRegister(old_val), !TYPE_UNSIGNED(TREE_TYPE(old_val)),
                    MemTy, !TYPE_UNSIGNED(TREE_TYPE(old_val)));
  Value *New_Val =
      CastToAnyType(EmitRegister(new_val), !TYPE_UNSIGNED(TREE_TYPE(new_val)),
                    MemTy, !TYPE_UNSIGNED(TREE_TYPE(new_val)));

  Value *C[3] = { Ptr, Old_Val, New_Val };
  Value *Result =
      Builder.CreateAtomicCmpXchg(C[0], C[1], C[2],
                                  SequentiallyConsistent,
                                  SequentiallyConsistent);

  // AtomicCmpXchg has the type {i1,iN}.
  Result = Builder.CreateExtractValue(Result, 0);

  if (isBool)
    Result = Builder.CreateICmpEQ(Result, Old_Val);
  tree return_type = gimple_call_return_type(stmt);
  Result = CastToAnyType(Result, !TYPE_UNSIGNED(return_type),
                         getRegType(return_type), !TYPE_UNSIGNED(return_type));
  return Reg2Mem(Result, return_type, Builder);
}

/// EmitBuiltinCall - stmt is a call to fndecl, a builtin function.  Try to emit
/// the call in a special way, setting Result to the scalar result if necessary.
/// If we can't handle the builtin, return false, otherwise return true.
bool TreeToLLVM::EmitBuiltinCall(gimple stmt, tree fndecl,
                                 const MemRef *DestLoc, Value *&Result) {
  if (DECL_BUILT_IN_CLASS(fndecl) == BUILT_IN_MD) {
    unsigned FnCode = DECL_FUNCTION_CODE(fndecl);
    if (TargetBuiltinCache.size() <= FnCode)
      TargetBuiltinCache.resize(FnCode + 1);

    // If we haven't converted this intrinsic over yet, do so now.
    if (TargetBuiltinCache[FnCode] == 0) {
      const char *TargetPrefix = "";
#ifdef LLVM_TARGET_INTRINSIC_PREFIX
      TargetPrefix = LLVM_TARGET_INTRINSIC_PREFIX;
#endif
      // If the backend has some special code to lower, go ahead and try to
      // do that first.
      if (EmitFrontendExpandedBuiltinCall(stmt, fndecl, DestLoc, Result))
        return true;

      // If this builtin directly corresponds to an LLVM intrinsic, get the
      // IntrinsicID now.
      const char *BuiltinName = IDENTIFIER_POINTER(DECL_NAME(fndecl));
      Intrinsic::ID IntrinsicID =
          Intrinsic::getIntrinsicForGCCBuiltin(TargetPrefix, BuiltinName);
      if (IntrinsicID == Intrinsic::not_intrinsic) {
        error("unsupported target builtin %<%s%> used", BuiltinName);
        Type *ResTy = ConvertType(gimple_call_return_type(stmt));
        if (ResTy->isSingleValueType())
          Result = UndefValue::get(ResTy);
        return true;
      }

      // Finally, map the intrinsic ID back to a name.
      TargetBuiltinCache[FnCode] =
          Intrinsic::getDeclaration(TheModule, IntrinsicID);
    }

    Result =
        EmitCallOf(TargetBuiltinCache[FnCode], stmt, DestLoc, AttributeSet());
    return true;
  }

  enum built_in_function fcode = DECL_FUNCTION_CODE(fndecl);
  switch (fcode) {
  default:
    return false;
    // Varargs builtins.
  case BUILT_IN_VA_START:
    return EmitBuiltinVAStart(stmt);
  case BUILT_IN_VA_END:
    return EmitBuiltinVAEnd(stmt);
  case BUILT_IN_VA_COPY:
    return EmitBuiltinVACopy(stmt);

  case BUILT_IN_ADJUST_TRAMPOLINE:
    return EmitBuiltinAdjustTrampoline(stmt, Result);
  case BUILT_IN_ALLOCA:
    return EmitBuiltinAlloca(stmt, Result);
#if (GCC_MINOR > 6)
  case BUILT_IN_ALLOCA_WITH_ALIGN:
    return EmitBuiltinAllocaWithAlign(stmt, Result);
#endif
#if (GCC_MINOR > 6)
  case BUILT_IN_ASSUME_ALIGNED:
    return EmitBuiltinAssumeAligned(stmt, Result);
#endif
  case BUILT_IN_BZERO:
    return EmitBuiltinBZero(stmt, Result);
  case BUILT_IN_CONSTANT_P:
    return EmitBuiltinConstantP(stmt, Result);
  case BUILT_IN_EXPECT:
    return EmitBuiltinExpect(stmt, Result);
  case BUILT_IN_EXTEND_POINTER:
    return EmitBuiltinExtendPointer(stmt, Result);
  case BUILT_IN_EXTRACT_RETURN_ADDR:
    return EmitBuiltinExtractReturnAddr(stmt, Result);
  case BUILT_IN_FRAME_ADDRESS:
    return EmitBuiltinReturnAddr(stmt, Result, true);
  case BUILT_IN_FROB_RETURN_ADDR:
    return EmitBuiltinFrobReturnAddr(stmt, Result);
  case BUILT_IN_INIT_TRAMPOLINE:
    return EmitBuiltinInitTrampoline(stmt, true);
#if (GCC_MINOR > 6)
  case BUILT_IN_INIT_HEAP_TRAMPOLINE:
    return EmitBuiltinInitTrampoline(stmt, false);
#endif
  case BUILT_IN_MEMCPY:
    return EmitBuiltinMemCopy(stmt, Result, false, false);
  case BUILT_IN_MEMCPY_CHK:
    return EmitBuiltinMemCopy(stmt, Result, false, true);
  case BUILT_IN_MEMMOVE:
    return EmitBuiltinMemCopy(stmt, Result, true, false);
  case BUILT_IN_MEMMOVE_CHK:
    return EmitBuiltinMemCopy(stmt, Result, true, true);
  case BUILT_IN_MEMSET:
    return EmitBuiltinMemSet(stmt, Result, false);
  case BUILT_IN_MEMSET_CHK:
    return EmitBuiltinMemSet(stmt, Result, true);
  case BUILT_IN_PREFETCH:
    return EmitBuiltinPrefetch(stmt);
  case BUILT_IN_RETURN_ADDRESS:
    return EmitBuiltinReturnAddr(stmt, Result, false);
  case BUILT_IN_STACK_RESTORE:
    return EmitBuiltinStackRestore(stmt);
  case BUILT_IN_STACK_SAVE:
    return EmitBuiltinStackSave(stmt, Result);
  case BUILT_IN_UNREACHABLE:
    return EmitBuiltinUnreachable();

    // Exception handling builtins.
  case BUILT_IN_EH_COPY_VALUES:
    return EmitBuiltinEHCopyValues(stmt);
  case BUILT_IN_EH_FILTER:
    return EmitBuiltinEHFilter(stmt, Result);
  case BUILT_IN_EH_POINTER:
    return EmitBuiltinEHPointer(stmt, Result);

    // Builtins used by the exception handling runtime.
  case BUILT_IN_DWARF_CFA:
    return EmitBuiltinDwarfCFA(stmt, Result);
#ifdef DWARF2_UNWIND_INFO
  case BUILT_IN_DWARF_SP_COLUMN:
    return EmitBuiltinDwarfSPColumn(stmt, Result);
  case BUILT_IN_INIT_DWARF_REG_SIZES:
    return EmitBuiltinInitDwarfRegSizes(stmt, Result);
#endif
  case BUILT_IN_EH_RETURN:
    return EmitBuiltinEHReturn(stmt, Result);
#ifdef EH_RETURN_DATA_REGNO
  case BUILT_IN_EH_RETURN_DATA_REGNO:
    return EmitBuiltinEHReturnDataRegno(stmt, Result);
#endif
  case BUILT_IN_UNWIND_INIT:
    return EmitBuiltinUnwindInit(stmt, Result);

  case BUILT_IN_OBJECT_SIZE: {
    if (!validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) {
      error("Invalid builtin_object_size argument types");
      return false;
    }
    tree ObjSizeTree = gimple_call_arg(stmt, 1);
    STRIP_NOPS(ObjSizeTree);
    if (!isa<INTEGER_CST>(ObjSizeTree) || tree_int_cst_sgn(ObjSizeTree) < 0 ||
        compare_tree_int(ObjSizeTree, 3) > 0) {
      error("Invalid second builtin_object_size argument");
      return false;
    }

    // LLVM doesn't handle type 1 or type 3. Deal with that here.
    Value *Tmp = EmitMemory(gimple_call_arg(stmt, 1));

    ConstantInt *CI = cast<ConstantInt>(Tmp);

    // Clear the bottom bit since we only handle whole objects and shift to turn
    // the second bit into our boolean.
    uint64_t val = (CI->getZExtValue() & 0x2) >> 1;

    Value *NewTy = ConstantInt::get(Tmp->getType(), val);

    Value *Args[] = { EmitMemory(gimple_call_arg(stmt, 0)), NewTy };
    Type *Int8PtrTy = Type::getInt8PtrTy(Context);

    // Grab the current return type.
    Type *Ty[2] = {
      ConvertType(gimple_call_return_type(stmt)),
      Int8PtrTy
    };

    // Manually coerce the arg to the correct pointer type.
    Args[0] = Builder.CreateBitCast(Args[0], Int8PtrTy);
    Args[1] = Builder.CreateIntCast(Args[1], Type::getInt1Ty(Context),
                                    /*isSigned*/ false);

    Result = Builder.CreateCall(
        Intrinsic::getDeclaration(TheModule, Intrinsic::objectsize, Ty), Args);
    return true;
  }
    // Unary bit counting intrinsics.
    // NOTE: do not merge these case statements.  That will cause the memoized
    // Function* to be incorrectly shared across the different typed functions.
  case BUILT_IN_CLZ: // These GCC builtins always return int.
  case BUILT_IN_CLZL:
  case BUILT_IN_CLZLL:
    Result = EmitBuiltinBitCountIntrinsic(stmt, Intrinsic::ctlz);
    return true;
  case BUILT_IN_CTZ: // These GCC builtins always return int.
  case BUILT_IN_CTZL:
  case BUILT_IN_CTZLL:
    Result = EmitBuiltinBitCountIntrinsic(stmt, Intrinsic::cttz);
    return true;
  case BUILT_IN_PARITYLL:
  case BUILT_IN_PARITYL:
  case BUILT_IN_PARITY: {
    Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
    EmitBuiltinUnaryOp(Amt, Result, Intrinsic::ctpop);
    Result = Builder.CreateBinOp(Instruction::And, Result,
                                 ConstantInt::get(Result->getType(), 1));
    tree return_type = gimple_call_return_type(stmt);
    Type *DestTy = ConvertType(return_type);
    Result = Builder.CreateIntCast(
        Result, DestTy, /*isSigned*/ !TYPE_UNSIGNED(return_type), "cast");
    return true;
  }
  case BUILT_IN_POPCOUNT: // These GCC builtins always return int.
  case BUILT_IN_POPCOUNTL:
  case BUILT_IN_POPCOUNTLL: {
    Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
    EmitBuiltinUnaryOp(Amt, Result, Intrinsic::ctpop);
    tree return_type = gimple_call_return_type(stmt);
    Type *DestTy = ConvertType(return_type);
    Result = Builder.CreateIntCast(
        Result, DestTy, /*isSigned*/ !TYPE_UNSIGNED(return_type), "cast");
    return true;
  }
  case BUILT_IN_BSWAP32:
  case BUILT_IN_BSWAP64: {
    Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
    EmitBuiltinUnaryOp(Amt, Result, Intrinsic::bswap);
    tree return_type = gimple_call_return_type(stmt);
    Type *DestTy = ConvertType(return_type);
    Result = Builder.CreateIntCast(
        Result, DestTy, /*isSigned*/ !TYPE_UNSIGNED(return_type), "cast");
    return true;
  }

  case BUILT_IN_SQRT:
  case BUILT_IN_SQRTF:
  case BUILT_IN_SQRTL:
    // The result of sqrt(negative) is implementation-defined, but follows
    // IEEE754 in most current implementations. llvm.sqrt, which has undefined
    // behavior for such inputs, is an inappropriate substitute.
    break;
  case BUILT_IN_POWI:
  case BUILT_IN_POWIF:
  case BUILT_IN_POWIL:
    Result = EmitBuiltinPOWI(stmt);
    return true;
  case BUILT_IN_POW:
  case BUILT_IN_POWF:
  case BUILT_IN_POWL:
    // If errno math has been disabled, expand these to llvm.pow calls.
    if (!flag_errno_math) {
      Result = EmitBuiltinPOW(stmt);
      return true;
    }
    break;
  case BUILT_IN_LOG:
  case BUILT_IN_LOGF:
  case BUILT_IN_LOGL:
    // If errno math has been disabled, expand these to llvm.log calls.
    if (!flag_errno_math) {
      Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
      EmitBuiltinUnaryOp(Amt, Result, Intrinsic::log);
      Result = CastToFPType(Result, ConvertType(gimple_call_return_type(stmt)));
      return true;
    }
    break;
  case BUILT_IN_LOG2:
  case BUILT_IN_LOG2F:
  case BUILT_IN_LOG2L:
    // If errno math has been disabled, expand these to llvm.log2 calls.
    if (!flag_errno_math) {
      Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
      EmitBuiltinUnaryOp(Amt, Result, Intrinsic::log2);
      Result = CastToFPType(Result, ConvertType(gimple_call_return_type(stmt)));
      return true;
    }
    break;
  case BUILT_IN_LOG10:
  case BUILT_IN_LOG10F:
  case BUILT_IN_LOG10L:
    // If errno math has been disabled, expand these to llvm.log10 calls.
    if (!flag_errno_math) {
      Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
      EmitBuiltinUnaryOp(Amt, Result, Intrinsic::log10);
      Result = CastToFPType(Result, ConvertType(gimple_call_return_type(stmt)));
      return true;
    }
    break;
  case BUILT_IN_EXP:
  case BUILT_IN_EXPF:
  case BUILT_IN_EXPL:
    // If errno math has been disabled, expand these to llvm.exp calls.
    if (!flag_errno_math) {
      Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
      EmitBuiltinUnaryOp(Amt, Result, Intrinsic::exp);
      Result = CastToFPType(Result, ConvertType(gimple_call_return_type(stmt)));
      return true;
    }
    break;
  case BUILT_IN_EXP2:
  case BUILT_IN_EXP2F:
  case BUILT_IN_EXP2L:
    // If errno math has been disabled, expand these to llvm.exp2 calls.
    if (!flag_errno_math) {
      Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
      EmitBuiltinUnaryOp(Amt, Result, Intrinsic::exp2);
      Result = CastToFPType(Result, ConvertType(gimple_call_return_type(stmt)));
      return true;
    }
    break;
  case BUILT_IN_FFS: // These GCC builtins always return int.
  case BUILT_IN_FFSL:
  case BUILT_IN_FFSLL: { // FFS(X) -> (x == 0 ? 0 : CTTZ(x)+1)
    // The argument and return type of cttz should match the argument type of
    // the ffs, but should ignore the return type of ffs.
    Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
    Result = Builder.CreateCall2(
        Intrinsic::getDeclaration(TheModule, Intrinsic::cttz, Amt->getType()),
        Amt, Builder.getTrue());
    Result = Builder.CreateAdd(Result, ConstantInt::get(Result->getType(), 1));
    Result = Builder.CreateIntCast(
        Result, ConvertType(gimple_call_return_type(stmt)), /*isSigned*/ false);
    Value *Cond =
        Builder.CreateICmpEQ(Amt, Constant::getNullValue(Amt->getType()));
    Result = Builder.CreateSelect(
        Cond, Constant::getNullValue(Result->getType()), Result);
    return true;
  }
#if (GCC_MINOR > 6)
  case BUILT_IN_ICEIL:
  case BUILT_IN_ICEILF:
  case BUILT_IN_ICEILL:
#endif
  case BUILT_IN_LCEIL:
  case BUILT_IN_LCEILF:
  case BUILT_IN_LCEILL:
  case BUILT_IN_LLCEIL:
  case BUILT_IN_LLCEILF:
  case BUILT_IN_LLCEILL:
    Result = EmitBuiltinLCEIL(stmt);
    return true;
#if (GCC_MINOR > 6)
  case BUILT_IN_IFLOOR:
  case BUILT_IN_IFLOORF:
  case BUILT_IN_IFLOORL:
#endif
  case BUILT_IN_LFLOOR:
  case BUILT_IN_LFLOORF:
  case BUILT_IN_LFLOORL:
  case BUILT_IN_LLFLOOR:
  case BUILT_IN_LLFLOORF:
  case BUILT_IN_LLFLOORL:
    Result = EmitBuiltinLFLOOR(stmt);
    return true;
#if (GCC_MINOR > 6)
  case BUILT_IN_IROUND:
  case BUILT_IN_IROUNDF:
  case BUILT_IN_IROUNDL:
#endif
  case BUILT_IN_LROUND:
  case BUILT_IN_LROUNDF:
  case BUILT_IN_LROUNDL:
    Result = EmitBuiltinLROUND(stmt);
    return true;
  case BUILT_IN_CEXPI:
  case BUILT_IN_CEXPIF:
  case BUILT_IN_CEXPIL:
    Result = EmitBuiltinCEXPI(stmt);
    return true;
    //TODO  case BUILT_IN_FLT_ROUNDS: {
    //TODO    Result =
    //TODO      Builder.CreateCall(Intrinsic::getDeclaration(TheModule,
    //TODO                                                   Intrinsic::flt_rounds));
    //TODO    Result = Builder.CreateBitCast(Result, ConvertType(gimple_call_return_type(stmt)));
    //TODO    return true;
    //TODO  }
  case BUILT_IN_SIGNBIT:
  case BUILT_IN_SIGNBITF:
  case BUILT_IN_SIGNBITL:
    Result = EmitBuiltinSIGNBIT(stmt);
    return true;
  case BUILT_IN_TRAP:
    Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::trap));
    // Emit an explicit unreachable instruction.
    Builder.CreateUnreachable();
    BeginBlock(BasicBlock::Create(Context));
    return true;

//TODO  // Convert annotation built-in to llvm.annotation intrinsic.
//TODO  case BUILT_IN_ANNOTATION: {
//TODO
//TODO    // Get file and line number
//TODO    location_t locus = gimple_location(stmt);
//TODO    Constant *lineNo = ConstantInt::get(Type::getInt32Ty, LOCATION_LINE(locus));
//TODO    Constant *file = ConvertMetadataStringToGV(LOCATION_FILE(locus));
//TODO    Type *SBP= Type::getInt8PtrTy(Context);
//TODO    file = TheFolder->CreateBitCast(file, SBP);
//TODO
//TODO    // Get arguments.
//TODO    tree arglist = CALL_EXPR_ARGS(stmt);
//TODO    Value *ExprVal = EmitMemory(gimple_call_arg(stmt, 0));
//TODO    Type *Ty = ExprVal->getType();
//TODO    Value *StrVal = EmitMemory(gimple_call_arg(stmt, 1));
//TODO
//TODO    SmallVector<Value *, 4> Args;
//TODO    Args.push_back(ExprVal);
//TODO    Args.push_back(StrVal);
//TODO    Args.push_back(file);
//TODO    Args.push_back(lineNo);
//TODO
//TODO    assert(Ty && "llvm.annotation arg type may not be null");
//TODO    Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule,
//TODO                                                          Intrinsic::annotation,
//TODO                                                          &Ty,
//TODO                                                          1),
//TODO                                Args.begin(), Args.end());
//TODO    return true;
//TODO  }

#if (GCC_MINOR < 7)
  case BUILT_IN_SYNCHRONIZE:
#else
  case BUILT_IN_SYNC_SYNCHRONIZE:
#endif
    // We assume like gcc appears to, that this only applies to cached memory.
    Builder.CreateFence(llvm::SequentiallyConsistent);
    return true;
#if defined(TARGET_ALPHA) || defined(TARGET_386) || defined(TARGET_POWERPC) || \
    defined(TARGET_ARM)
// gcc uses many names for the sync intrinsics
// The type of the first argument is not reliable for choosing the
// right llvm function; if the original type is not volatile, gcc has
// helpfully changed it to "volatile void *" at this point.  The
// original type can be recovered from the function type in most cases.
// For lock_release and bool_compare_and_swap even that is not good
// enough, we have to key off the opcode.
// Note that Intrinsic::getDeclaration expects the type list in reversed
// order, while CreateCall expects the parameter list in normal order.
#if (GCC_MINOR < 7)
  case BUILT_IN_BOOL_COMPARE_AND_SWAP_1:
#else
  case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
#endif
    Result = BuildCmpAndSwapAtomic(stmt, BITS_PER_UNIT, true);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_BOOL_COMPARE_AND_SWAP_2:
#else
  case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
#endif
    Result = BuildCmpAndSwapAtomic(stmt, 2 * BITS_PER_UNIT, true);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_BOOL_COMPARE_AND_SWAP_4:
#else
  case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
#endif
    Result = BuildCmpAndSwapAtomic(stmt, 4 * BITS_PER_UNIT, true);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_BOOL_COMPARE_AND_SWAP_8:
#else
  case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
    Result = BuildCmpAndSwapAtomic(stmt, 8 * BITS_PER_UNIT, true);
    return true;

// Fall through.
#if (GCC_MINOR < 7)
  case BUILT_IN_VAL_COMPARE_AND_SWAP_1:
#else
  case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
#endif
    Result = BuildCmpAndSwapAtomic(stmt, BITS_PER_UNIT, false);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_VAL_COMPARE_AND_SWAP_2:
#else
  case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
#endif
    Result = BuildCmpAndSwapAtomic(stmt, 2 * BITS_PER_UNIT, false);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_VAL_COMPARE_AND_SWAP_4:
#else
  case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
#endif
    Result = BuildCmpAndSwapAtomic(stmt, 4 * BITS_PER_UNIT, false);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_VAL_COMPARE_AND_SWAP_8:
#else
  case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
    Result = BuildCmpAndSwapAtomic(stmt, 8 * BITS_PER_UNIT, false);
    return true;

#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_ADD_8:
#else
  case BUILT_IN_SYNC_FETCH_AND_ADD_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_ADD_1:
  case BUILT_IN_FETCH_AND_ADD_2:
  case BUILT_IN_FETCH_AND_ADD_4: {
#else
  case BUILT_IN_SYNC_FETCH_AND_ADD_1:
  case BUILT_IN_SYNC_FETCH_AND_ADD_2:
  case BUILT_IN_SYNC_FETCH_AND_ADD_4: {
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::Add);
    return true;
  }
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_SUB_8:
#else
  case BUILT_IN_SYNC_FETCH_AND_SUB_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_SUB_1:
  case BUILT_IN_FETCH_AND_SUB_2:
  case BUILT_IN_FETCH_AND_SUB_4: {
#else
  case BUILT_IN_SYNC_FETCH_AND_SUB_1:
  case BUILT_IN_SYNC_FETCH_AND_SUB_2:
  case BUILT_IN_SYNC_FETCH_AND_SUB_4: {
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::Sub);
    return true;
  }
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_OR_8:
#else
  case BUILT_IN_SYNC_FETCH_AND_OR_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_OR_1:
  case BUILT_IN_FETCH_AND_OR_2:
  case BUILT_IN_FETCH_AND_OR_4: {
#else
  case BUILT_IN_SYNC_FETCH_AND_OR_1:
  case BUILT_IN_SYNC_FETCH_AND_OR_2:
  case BUILT_IN_SYNC_FETCH_AND_OR_4: {
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::Or);
    return true;
  }
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_AND_8:
#else
  case BUILT_IN_SYNC_FETCH_AND_AND_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_AND_1:
  case BUILT_IN_FETCH_AND_AND_2:
  case BUILT_IN_FETCH_AND_AND_4: {
#else
  case BUILT_IN_SYNC_FETCH_AND_AND_1:
  case BUILT_IN_SYNC_FETCH_AND_AND_2:
  case BUILT_IN_SYNC_FETCH_AND_AND_4: {
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::And);
    return true;
  }
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_XOR_8:
#else
  case BUILT_IN_SYNC_FETCH_AND_XOR_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_XOR_1:
  case BUILT_IN_FETCH_AND_XOR_2:
  case BUILT_IN_FETCH_AND_XOR_4: {
#else
  case BUILT_IN_SYNC_FETCH_AND_XOR_1:
  case BUILT_IN_SYNC_FETCH_AND_XOR_2:
  case BUILT_IN_SYNC_FETCH_AND_XOR_4: {
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::Xor);
    return true;
  }
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_NAND_8:
#else
  case BUILT_IN_SYNC_FETCH_AND_NAND_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_FETCH_AND_NAND_1:
  case BUILT_IN_FETCH_AND_NAND_2:
  case BUILT_IN_FETCH_AND_NAND_4: {
#else
  case BUILT_IN_SYNC_FETCH_AND_NAND_1:
  case BUILT_IN_SYNC_FETCH_AND_NAND_2:
  case BUILT_IN_SYNC_FETCH_AND_NAND_4: {
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::Nand);
    return true;
  }
#if (GCC_MINOR < 7)
  case BUILT_IN_LOCK_TEST_AND_SET_8:
#else
  case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_LOCK_TEST_AND_SET_1:
  case BUILT_IN_LOCK_TEST_AND_SET_2:
  case BUILT_IN_LOCK_TEST_AND_SET_4: {
#else
  case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
  case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
  case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4: {
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::Xchg);
    return true;
  }

#if (GCC_MINOR < 7)
  case BUILT_IN_ADD_AND_FETCH_8:
#else
  case BUILT_IN_SYNC_ADD_AND_FETCH_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_ADD_AND_FETCH_1:
  case BUILT_IN_ADD_AND_FETCH_2:
  case BUILT_IN_ADD_AND_FETCH_4:
#else
  case BUILT_IN_SYNC_ADD_AND_FETCH_1:
  case BUILT_IN_SYNC_ADD_AND_FETCH_2:
  case BUILT_IN_SYNC_ADD_AND_FETCH_4:
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::Add, Instruction::Add);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_SUB_AND_FETCH_8:
#else
  case BUILT_IN_SYNC_SUB_AND_FETCH_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_SUB_AND_FETCH_1:
  case BUILT_IN_SUB_AND_FETCH_2:
  case BUILT_IN_SUB_AND_FETCH_4:
#else
  case BUILT_IN_SYNC_SUB_AND_FETCH_1:
  case BUILT_IN_SYNC_SUB_AND_FETCH_2:
  case BUILT_IN_SYNC_SUB_AND_FETCH_4:
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::Sub, Instruction::Sub);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_OR_AND_FETCH_8:
#else
  case BUILT_IN_SYNC_OR_AND_FETCH_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_OR_AND_FETCH_1:
  case BUILT_IN_OR_AND_FETCH_2:
  case BUILT_IN_OR_AND_FETCH_4:
#else
  case BUILT_IN_SYNC_OR_AND_FETCH_1:
  case BUILT_IN_SYNC_OR_AND_FETCH_2:
  case BUILT_IN_SYNC_OR_AND_FETCH_4:
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::Or, Instruction::Or);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_AND_AND_FETCH_8:
#else
  case BUILT_IN_SYNC_AND_AND_FETCH_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_AND_AND_FETCH_1:
  case BUILT_IN_AND_AND_FETCH_2:
  case BUILT_IN_AND_AND_FETCH_4:
#else
  case BUILT_IN_SYNC_AND_AND_FETCH_1:
  case BUILT_IN_SYNC_AND_AND_FETCH_2:
  case BUILT_IN_SYNC_AND_AND_FETCH_4:
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::And, Instruction::And);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_XOR_AND_FETCH_8:
#else
  case BUILT_IN_SYNC_XOR_AND_FETCH_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_XOR_AND_FETCH_1:
  case BUILT_IN_XOR_AND_FETCH_2:
  case BUILT_IN_XOR_AND_FETCH_4:
#else
  case BUILT_IN_SYNC_XOR_AND_FETCH_1:
  case BUILT_IN_SYNC_XOR_AND_FETCH_2:
  case BUILT_IN_SYNC_XOR_AND_FETCH_4:
#endif
    Result = BuildBinaryAtomic(stmt, AtomicRMWInst::Xor, Instruction::Xor);
    return true;
#if (GCC_MINOR < 7)
  case BUILT_IN_NAND_AND_FETCH_8:
#else
  case BUILT_IN_SYNC_NAND_AND_FETCH_8:
#endif
#if defined(TARGET_POWERPC)
    if (!TARGET_64BIT)
      return false;
#endif
#if (GCC_MINOR < 7)
  case BUILT_IN_NAND_AND_FETCH_1:
  case BUILT_IN_NAND_AND_FETCH_2:
  case BUILT_IN_NAND_AND_FETCH_4: {
#else
  case BUILT_IN_SYNC_NAND_AND_FETCH_1:
  case BUILT_IN_SYNC_NAND_AND_FETCH_2:
  case BUILT_IN_SYNC_NAND_AND_FETCH_4: {
#endif
    tree return_type = gimple_call_return_type(stmt);
    Type *ResultTy = ConvertType(return_type);
    Value *C[2] = { EmitMemory(gimple_call_arg(stmt, 0)),
                    EmitMemory(gimple_call_arg(stmt, 1)) };
    C[0] = Builder.CreateBitCast(C[0], ResultTy->getPointerTo());
    C[1] = Builder.CreateIntCast(
        C[1], ResultTy, /*isSigned*/ !TYPE_UNSIGNED(return_type), "cast");
    Result = Builder.CreateAtomicRMW(AtomicRMWInst::Nand, C[0], C[1],
                                     SequentiallyConsistent);

    Result = Builder.CreateAnd(Builder.CreateNot(Result), C[1]);
    Result = Builder.CreateIntToPtr(Result, ResultTy);
    return true;
  }

#if (GCC_MINOR < 7)
  case BUILT_IN_LOCK_RELEASE_1:
  case BUILT_IN_LOCK_RELEASE_2:
  case BUILT_IN_LOCK_RELEASE_4:
  case BUILT_IN_LOCK_RELEASE_8:
  case BUILT_IN_LOCK_RELEASE_16: {
#else
  case BUILT_IN_SYNC_LOCK_RELEASE_1:
  case BUILT_IN_SYNC_LOCK_RELEASE_2:
  case BUILT_IN_SYNC_LOCK_RELEASE_4:
  case BUILT_IN_SYNC_LOCK_RELEASE_8:
  case BUILT_IN_SYNC_LOCK_RELEASE_16: {
#endif
    // This is effectively a volatile store of 0, and has no return value.
    // The argument has typically been coerced to "volatile void*"; the
    // only way to find the size of the operation is from the builtin
    // opcode.
    // FIXME: This is wrong; it works to some extent on x86 if the optimizer
    // doesn't get too clever, and is horribly broken anywhere else.  It needs
    // to use "store atomic [...] release".
    Type *Ty;
    switch (DECL_FUNCTION_CODE(fndecl)) {
#if (GCC_MINOR < 7)
    case BUILT_IN_LOCK_RELEASE_16: // not handled; should use SSE on x86
#else
    case BUILT_IN_SYNC_LOCK_RELEASE_16: // not handled; should use SSE on x86
#endif
    default:
      llvm_unreachable("Not handled; should use SSE on x86!");
#if (GCC_MINOR < 7)
    case BUILT_IN_LOCK_RELEASE_1:
#else
    case BUILT_IN_SYNC_LOCK_RELEASE_1:
#endif
      Ty = Type::getInt8Ty(Context);
      break;
#if (GCC_MINOR < 7)
    case BUILT_IN_LOCK_RELEASE_2:
#else
    case BUILT_IN_SYNC_LOCK_RELEASE_2:
#endif
      Ty = Type::getInt16Ty(Context);
      break;
#if (GCC_MINOR < 7)
    case BUILT_IN_LOCK_RELEASE_4:
#else
    case BUILT_IN_SYNC_LOCK_RELEASE_4:
#endif
      Ty = Type::getInt32Ty(Context);
      break;
#if (GCC_MINOR < 7)
    case BUILT_IN_LOCK_RELEASE_8:
#else
    case BUILT_IN_SYNC_LOCK_RELEASE_8:
#endif
      Ty = Type::getInt64Ty(Context);
      break;
    }
    Value *Ptr = EmitMemory(gimple_call_arg(stmt, 0));
    Ptr = Builder.CreateBitCast(Ptr, Ty->getPointerTo());
    Builder.CreateStore(Constant::getNullValue(Ty), Ptr, true);
    Result = 0;
    return true;
  }

#endif //FIXME: these break the build for backends that haven't implemented them

#if 1 // FIXME: Should handle these GCC extensions eventually.
  case BUILT_IN_LONGJMP: {
    if (validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) {
      tree value = gimple_call_arg(stmt, 1);

      if (!isa<INTEGER_CST>(value) ||
          cast<ConstantInt>(EmitMemory(value))->getValue() != 1) {
        error("%<__builtin_longjmp%> second argument must be 1");
        return false;
      }
    }
#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H)
    Value *Buf = Emit(TREE_VALUE(arglist), 0);
    Buf = Builder.CreateBitCast(Buf, Type::getInt8Ty(Context)->getPointerTo());
    Builder.CreateCall(
        Intrinsic::getDeclaration(TheModule, Intrinsic::eh_sjlj_longjmp), Buf);
    Result = 0;
    return true;
#endif
    // Fall-through
  }
  case BUILT_IN_APPLY_ARGS:
  case BUILT_IN_APPLY:
  case BUILT_IN_RETURN:
  case BUILT_IN_SAVEREGS:
#if (GCC_MINOR < 6)
  case BUILT_IN_ARGS_INFO:
#endif
  case BUILT_IN_NEXT_ARG:
  case BUILT_IN_CLASSIFY_TYPE:
  case BUILT_IN_AGGREGATE_INCOMING_ADDRESS:
  case BUILT_IN_SETJMP_SETUP:
  case BUILT_IN_SETJMP_DISPATCHER:
  case BUILT_IN_SETJMP_RECEIVER:
  case BUILT_IN_UPDATE_SETJMP_BUF:
      // FIXME: HACK: Just ignore these.
      {
    Type *Ty = ConvertType(gimple_call_return_type(stmt));
    if (!Ty->isVoidTy())
      Result = Constant::getNullValue(Ty);
    return true;
  }
#endif // FIXME: Should handle these GCC extensions eventually.
  }
    return false;
  }

    bool TreeToLLVM::EmitBuiltinUnaryOp(Value * InVal, Value * &Result,
                                        Intrinsic::ID Id) {
      // The intrinsic might be overloaded in which case the argument is of
      // varying type. Make sure that we specify the actual type for "iAny"
      // by passing it as the 3rd and 4th parameters. This isn't needed for
      // most intrinsics, but is needed for ctpop, cttz, ctlz.
      Type *Ty = InVal->getType();
      Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Id, Ty),
                                  InVal);
      return true;
    }

    Value *TreeToLLVM::EmitBuiltinBitCountIntrinsic(gimple stmt,
                                                    Intrinsic::ID Id) {
      Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
      Value *Result = Builder.CreateCall2(
          Intrinsic::getDeclaration(TheModule, Id, Amt->getType()), Amt,
          Builder.getTrue());
      tree return_type = gimple_call_return_type(stmt);
      Type *DestTy = ConvertType(return_type);
      return Builder.CreateIntCast(
          Result, DestTy, /*isSigned*/ !TYPE_UNSIGNED(return_type), "cast");
    }

    Value *TreeToLLVM::EmitBuiltinSQRT(gimple stmt) {
      Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
      Type *Ty = Amt->getType();

      return Builder.CreateCall(
          Intrinsic::getDeclaration(TheModule, Intrinsic::sqrt, Ty), Amt);
    }

    Value *TreeToLLVM::EmitBuiltinPOWI(gimple stmt) {
      if (!validate_gimple_arglist(stmt, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
        return 0;

      Value *Val = EmitMemory(gimple_call_arg(stmt, 0));
      Value *Pow = EmitMemory(gimple_call_arg(stmt, 1));
      Type *Ty = Val->getType();
      Pow = Builder.CreateIntCast(Pow, Type::getInt32Ty(Context),
                                  /*isSigned*/ true);

      SmallVector<Value *, 2> Args;
      Args.push_back(Val);
      Args.push_back(Pow);
      return Builder.CreateCall(
          Intrinsic::getDeclaration(TheModule, Intrinsic::powi, Ty), Args);
    }

    Value *TreeToLLVM::EmitBuiltinPOW(gimple stmt) {
      if (!validate_gimple_arglist(stmt, REAL_TYPE, REAL_TYPE, VOID_TYPE))
        return 0;

      Value *Val = EmitMemory(gimple_call_arg(stmt, 0));
      Value *Pow = EmitMemory(gimple_call_arg(stmt, 1));
      Type *Ty = Val->getType();

      SmallVector<Value *, 2> Args;
      Args.push_back(Val);
      Args.push_back(Pow);
      return Builder.CreateCall(
          Intrinsic::getDeclaration(TheModule, Intrinsic::pow, Ty), Args);
    }

    Value *TreeToLLVM::EmitBuiltinLCEIL(gimple stmt) {
      if (!validate_gimple_arglist(stmt, REAL_TYPE, VOID_TYPE))
        return 0;

      // Cast the result of "ceil" to the appropriate integer type.
      // First call the appropriate version of "ceil".
      tree op = gimple_call_arg(stmt, 0);
      StringRef Name = SelectFPName(TREE_TYPE(op), "ceilf", "ceil", "ceill");
      assert(!Name.empty() && "Unsupported floating point type!");
      CallInst *Call = EmitSimpleCall(Name, TREE_TYPE(op), op, NULL);
      Call->setDoesNotThrow();
      Call->setDoesNotAccessMemory();

      // Then type cast the result of the "ceil" call.
      tree type = gimple_call_return_type(stmt);
      Type *RetTy = getRegType(type);
      return TYPE_UNSIGNED(type) ? Builder.CreateFPToUI(Call, RetTy)
                                 : Builder.CreateFPToSI(Call, RetTy);
    }

    Value *TreeToLLVM::EmitBuiltinLFLOOR(gimple stmt) {
      if (!validate_gimple_arglist(stmt, REAL_TYPE, VOID_TYPE))
        return 0;

      // Cast the result of "floor" to the appropriate integer type.
      // First call the appropriate version of "floor".
      tree op = gimple_call_arg(stmt, 0);
      StringRef Name = SelectFPName(TREE_TYPE(op), "floorf", "floor", "floorl");
      assert(!Name.empty() && "Unsupported floating point type!");
      CallInst *Call = EmitSimpleCall(Name, TREE_TYPE(op), op, NULL);
      Call->setDoesNotThrow();
      Call->setDoesNotAccessMemory();

      // Then type cast the result of the "floor" call.
      tree type = gimple_call_return_type(stmt);
      Type *RetTy = getRegType(type);
      return TYPE_UNSIGNED(type) ? Builder.CreateFPToUI(Call, RetTy)
                                 : Builder.CreateFPToSI(Call, RetTy);
    }

    Value *TreeToLLVM::EmitBuiltinLROUND(gimple stmt) {
      if (!validate_gimple_arglist(stmt, REAL_TYPE, VOID_TYPE))
        return 0;

      // Cast the result of "lround" to the appropriate integer type.
      // First call the appropriate version of "lround".
      tree op = gimple_call_arg(stmt, 0);
      StringRef Name = SelectFPName(TREE_TYPE(op),
                                    "lroundf", "lround", "lroundl");
      assert(!Name.empty() && "Unsupported floating point type!");
      CallInst *Call = EmitSimpleCall(Name, long_integer_type_node, op, NULL);
      Call->setDoesNotThrow();
      Call->setDoesNotAccessMemory();

      // Then type cast the result of the "lround" call.
      tree type = gimple_call_return_type(stmt);
      Type *RetTy = getRegType(type);
      return Builder.CreateTrunc(Call, RetTy);
    }

    Value *TreeToLLVM::EmitBuiltinCEXPI(gimple stmt) {
      if (!validate_gimple_arglist(stmt, REAL_TYPE, VOID_TYPE))
        return 0;

      if (TARGET_HAS_SINCOS) {
        // exp(i*arg) = cos(arg) + i*sin(arg).  Emit a call to sincos.  First
        // determine which version of sincos to call.
        tree arg = gimple_call_arg(stmt, 0);
        tree arg_type = TREE_TYPE(arg);
        StringRef Name = SelectFPName(arg_type, "sincosf", "sincos", "sincosl");
        assert(!Name.empty() && "Unsupported floating point type!");

        // Create stack slots to store the real (cos) and imaginary (sin) parts in.
        Value *Val = EmitRegister(arg);
        Value *SinPtr = CreateTemporary(Val->getType());
        Value *CosPtr = CreateTemporary(Val->getType());

        // Get the LLVM function declaration for sincos.
        Type *ArgTys[3] = { Val->getType(), SinPtr->getType(),
                            CosPtr->getType() };
        FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), ArgTys,
                                              /*isVarArg*/ false);
        Constant *Func = TheModule->getOrInsertFunction(Name, FTy);

        // Determine the calling convention.
        CallingConv::ID CC = CallingConv::C;
#ifdef TARGET_ADJUST_LLVM_CC
        // Query the target for the calling convention to use.
        tree fntype = build_function_type_list(
            void_type_node, arg_type, TYPE_POINTER_TO(arg_type),
            TYPE_POINTER_TO(arg_type), NULL_TREE);
        TARGET_ADJUST_LLVM_CC(CC, fntype);
#endif

        // If the function already existed with the wrong prototype then don't try to
        // muck with its calling convention.  Otherwise, set the calling convention.
        if (Function *F = llvm::dyn_cast<Function>(Func))
          F->setCallingConv(CC);

        // Call sincos.
        Value *Args[3] = { Val, SinPtr, CosPtr };
        CallInst *CI = Builder.CreateCall(Func, Args);
        CI->setCallingConv(CC);
        CI->setDoesNotThrow();

        // Load out the real (cos) and imaginary (sin) parts.
        Value *Sin = Builder.CreateLoad(SinPtr);
        Value *Cos = Builder.CreateLoad(CosPtr);

        // Return the complex number "cos(arg) + i*sin(arg)".
        return CreateComplex(Cos, Sin);
      } else {
        // Emit a call to cexp.  First determine which version of cexp to call.
        tree arg = gimple_call_arg(stmt, 0);
        tree arg_type = TREE_TYPE(arg);
        StringRef Name = SelectFPName(arg_type, "cexpf", "cexp", "cexpl");
        assert(!Name.empty() && "Unsupported floating point type!");

        // Get the GCC and LLVM function types for cexp.
        tree cplx_type = gimple_call_return_type(stmt);
        tree fntype = build_function_type_list(cplx_type, cplx_type, NULL_TREE);
        FunctionType *FTy = cast<FunctionType>(ConvertType(fntype));

        // Get the LLVM function declaration for cexp.
        Constant *Func = TheModule->getOrInsertFunction(Name, FTy);

        // Determine the calling convention.
        CallingConv::ID CC = CallingConv::C;
#ifdef TARGET_ADJUST_LLVM_CC
        // Query the target for the calling convention to use.
        TARGET_ADJUST_LLVM_CC(CC, fntype);
#endif

        // If the function already existed with the wrong prototype then don't try to
        // muck with its calling convention.  Otherwise, set the calling convention.
        if (Function *F = llvm::dyn_cast<Function>(Func))
          F->setCallingConv(CC);

        // Form the complex number "0 + i*arg".
        Value *Arg = EmitRegister(arg);
        Value *CplxArg =
            CreateComplex(Constant::getNullValue(Arg->getType()), Arg);

        // Call cexp and return the result.  This is rather painful because complex
        // numbers may be passed in funky ways and we don't have a proper interface
        // for marshalling call parameters.
        SmallVector<Value *, 16> CallOperands;
        FunctionCallArgumentConversion Client(CallOperands, FTy, /*destloc*/ 0,
                                              /*ReturnSlotOpt*/ false, Builder,
                                              CC);
        DefaultABI ABIConverter(Client);

        // Handle the result.
        ABIConverter.HandleReturnType(cplx_type, fntype, false);

        // Push the argument.
        bool PassedInMemory;
        Type *CplxTy = CplxArg->getType();
        if (LLVM_SHOULD_PASS_AGGREGATE_AS_FCA(cplx_type, CplxTy)) {
          Client.pushValue(CplxArg);
          PassedInMemory = false;
        } else {
          // Push the address of a temporary copy.
          MemRef Copy = CreateTempLoc(CplxTy);
          StoreRegisterToMemory(CplxArg, Copy, cplx_type, 0, Builder);
          Client.pushAddress(Copy.Ptr);
          PassedInMemory = true;
        }

        AttrBuilder AttrBuilder;
        std::vector<Type *> ScalarArgs;
        ABIConverter.HandleArgument(cplx_type, ScalarArgs, &AttrBuilder);
        assert(!AttrBuilder.hasAttributes() &&
               "Got attributes but none given!");
        Client.clear();

        // Create the call.
        CallInst *CI = Builder.CreateCall(Func, CallOperands);
        CI->setCallingConv(CC);
        CI->setDoesNotThrow();
        if (!PassedInMemory)
          CI->setDoesNotAccessMemory();

        // Extract and return the result.
        if (Client.isShadowReturn())
          return Client.EmitShadowResult(cplx_type, 0);

        if (Client.isAggrReturn()) {
          // Extract to a temporary then load the value out later.
          MemRef Target = CreateTempLoc(CplxTy);

          assert(DL.getTypeAllocSize(CI->getType()) <=
                 DL.getTypeAllocSize(CplxTy) &&
                 "Complex number returned in too large registers!");
          Value *Dest =
              Builder.CreateBitCast(Target.Ptr, CI->getType()->getPointerTo());
          LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(CI, Dest, Target.Volatile,
                                             Builder);
          return Builder.CreateLoad(Target.Ptr);
        }

        if (CI->getType() == CplxTy)
          return CI; // Normal scalar return.

        // Probably { float, float } being returned as a double.
        assert(DL.getTypeAllocSize(CI->getType()) ==
               DL.getTypeAllocSize(CplxTy) &&
               "Size mismatch in scalar to scalar conversion!");
        Value *Tmp = CreateTemporary(CI->getType());
        Builder.CreateStore(CI, Tmp);
        Type *CplxPtrTy = CplxTy->getPointerTo();
        return Builder.CreateLoad(Builder.CreateBitCast(Tmp, CplxPtrTy));
      }
    }

    Value *TreeToLLVM::EmitBuiltinSIGNBIT(gimple stmt) {
      Value *Arg = EmitRegister(gimple_call_arg(stmt, 0));
      Type *ArgTy = Arg->getType();
      unsigned ArgWidth = ArgTy->getPrimitiveSizeInBits();
      Type *ArgIntTy = IntegerType::get(Context, ArgWidth);
      Value *BCArg = Builder.CreateBitCast(Arg, ArgIntTy);
      Value *ZeroCmp = Constant::getNullValue(ArgIntTy);
      Value *Result = Builder.CreateICmpSLT(BCArg, ZeroCmp);
      return Builder.CreateZExt(Result,
                                ConvertType(gimple_call_return_type(stmt)));
    }

    bool TreeToLLVM::EmitBuiltinConstantP(gimple stmt, Value * &Result) {
      Result =
          Constant::getNullValue(ConvertType(gimple_call_return_type(stmt)));
      return true;
    }

    bool TreeToLLVM::EmitBuiltinExtendPointer(gimple stmt, Value * &Result) {
      tree arg0 = gimple_call_arg(stmt, 0);
      Value *Amt = EmitMemory(arg0);
      bool AmtIsSigned = !TYPE_UNSIGNED(TREE_TYPE(arg0));
      bool ExpIsSigned = !TYPE_UNSIGNED(gimple_call_return_type(stmt));
      Result = CastToAnyType(Amt, AmtIsSigned,
                             ConvertType(gimple_call_return_type(stmt)),
                             ExpIsSigned);
      return true;
    }

    /// OptimizeIntoPlainBuiltIn - Return true if it's safe to lower the object
    /// size checking builtin calls (e.g. __builtin___memcpy_chk into the
    /// plain non-checking calls. If the size of the argument is either -1 (unknown)
    /// or large enough to ensure no overflow (> len), then it's safe to do so.
    static bool OptimizeIntoPlainBuiltIn(gimple stmt, Value * Len,
                                         Value * Size) {
      if (BitCastInst *SizeBC = llvm::dyn_cast<BitCastInst>(Size))
        Size = SizeBC->getOperand(0);
      ConstantInt *SizeCI = llvm::dyn_cast<ConstantInt>(Size);
      if (!SizeCI)
        return false;
      if (SizeCI->isAllOnesValue())
        // If size is -1, convert to plain memcpy, etc.
        return true;

      if (BitCastInst *LenBC = llvm::dyn_cast<BitCastInst>(Len))
        Len = LenBC->getOperand(0);
      ConstantInt *LenCI = llvm::dyn_cast<ConstantInt>(Len);
      if (!LenCI)
        return false;
      if (SizeCI->getValue().ult(LenCI->getValue())) {
        warning(0, "call to %D will always overflow destination buffer",
                gimple_call_fndecl(stmt));
        return false;
      }
      return true;
    }

    /// EmitBuiltinMemCopy - Emit an llvm.memcpy or llvm.memmove intrinsic,
    /// depending on the value of isMemMove.
    bool TreeToLLVM::EmitBuiltinMemCopy(gimple stmt, Value * &Result,
                                        bool isMemMove, bool SizeCheck) {
      if (SizeCheck) {
        if (!validate_gimple_arglist(stmt, POINTER_TYPE, POINTER_TYPE,
                                     INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
          return false;
      } else {
        if (!validate_gimple_arglist(stmt, POINTER_TYPE, POINTER_TYPE,
                                     INTEGER_TYPE, VOID_TYPE))
          return false;
      }

      tree Dst = gimple_call_arg(stmt, 0);
      tree Src = gimple_call_arg(stmt, 1);
      unsigned SrcAlign = getPointerAlignment(Src);
      unsigned DstAlign = getPointerAlignment(Dst);

      Value *DstV = EmitMemory(Dst);
      Value *SrcV = EmitMemory(Src);
      Value *Len = EmitMemory(gimple_call_arg(stmt, 2));
      if (SizeCheck) {
        tree SizeArg = gimple_call_arg(stmt, 3);
        Value *Size = EmitMemory(SizeArg);
        if (!OptimizeIntoPlainBuiltIn(stmt, Len, Size))
          return false;
      }

      Result =
          isMemMove ? EmitMemMove(DstV, SrcV, Len, std::min(SrcAlign, DstAlign))
                    : EmitMemCpy(DstV, SrcV, Len, std::min(SrcAlign, DstAlign));
      return true;
    }

    bool TreeToLLVM::EmitBuiltinMemSet(gimple stmt, Value * &Result,
                                       bool SizeCheck) {
      if (SizeCheck) {
        if (!validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE,
                                     INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
          return false;
      } else {
        if (!validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE,
                                     INTEGER_TYPE, VOID_TYPE))
          return false;
      }

      tree Dst = gimple_call_arg(stmt, 0);
      unsigned DstAlign = getPointerAlignment(Dst);

      Value *DstV = EmitMemory(Dst);
      Value *Val = EmitMemory(gimple_call_arg(stmt, 1));
      Value *Len = EmitMemory(gimple_call_arg(stmt, 2));
      if (SizeCheck) {
        tree SizeArg = gimple_call_arg(stmt, 3);
        Value *Size = EmitMemory(SizeArg);
        if (!OptimizeIntoPlainBuiltIn(stmt, Len, Size))
          return false;
      }
      Result = EmitMemSet(DstV, Val, Len, DstAlign);
      return true;
    }

    bool TreeToLLVM::EmitBuiltinBZero(gimple stmt, Value * &/*Result*/) {
      if (!validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
        return false;

      tree Dst = gimple_call_arg(stmt, 0);
      unsigned DstAlign = getPointerAlignment(Dst);

      Value *DstV = EmitMemory(Dst);
      Value *Val = Constant::getNullValue(Type::getInt32Ty(Context));
      Value *Len = EmitMemory(gimple_call_arg(stmt, 1));
      EmitMemSet(DstV, Val, Len, DstAlign);
      return true;
    }

    bool TreeToLLVM::EmitBuiltinPrefetch(gimple stmt) {
      if (!validate_gimple_arglist(stmt, POINTER_TYPE, 0))
        return false;

      Value *Ptr = EmitMemory(gimple_call_arg(stmt, 0));
      Value *ReadWrite = 0;
      Value *Locality = 0;
      Value *Data = 0;

      if (gimple_call_num_args(stmt) > 1) { // Args 1/2 are optional
        ReadWrite = EmitMemory(gimple_call_arg(stmt, 1));
        if (!isa<ConstantInt>(ReadWrite)) {
          error("second argument to %<__builtin_prefetch%> must be a constant");
          ReadWrite = 0;
        } else if (cast<ConstantInt>(ReadWrite)->getZExtValue() > 1) {
          warning(0, "invalid second argument to %<__builtin_prefetch%>;"
                     " using zero");
          ReadWrite = 0;
        } else {
          ReadWrite = TheFolder->CreateIntCast(cast<Constant>(ReadWrite),
                                               Type::getInt32Ty(Context),
                                               /*isSigned*/ false);
        }

        if (gimple_call_num_args(stmt) > 2) {
          Locality = EmitMemory(gimple_call_arg(stmt, 2));
          if (!isa<ConstantInt>(Locality)) {
            error(
                "third argument to %<__builtin_prefetch%> must be a constant");
            Locality = 0;
          } else if (cast<ConstantInt>(Locality)->getZExtValue() > 3) {
            warning(
                0, "invalid third argument to %<__builtin_prefetch%>; using 3");
            Locality = 0;
          } else {
            Locality = TheFolder->CreateIntCast(cast<Constant>(Locality),
                                                Type::getInt32Ty(Context),
                                                /*isSigned*/ false);
          }
        }
      }

      // Default to highly local read.
      if (ReadWrite == 0)
        ReadWrite = Builder.getInt32(0);
      if (Locality == 0)
        Locality = Builder.getInt32(3);
      if (Data == 0)
        Data = Builder.getInt32(1);

      Ptr = Builder.CreateBitCast(Ptr, Type::getInt8PtrTy(Context));

      Builder.CreateCall4(
          Intrinsic::getDeclaration(TheModule, Intrinsic::prefetch), Ptr,
          ReadWrite, Locality, Data);
      return true;
    }

    /// EmitBuiltinReturnAddr - Emit an llvm.returnaddress or llvm.frameaddress
    /// instruction, depending on whether isFrame is true or not.
    bool TreeToLLVM::EmitBuiltinReturnAddr(gimple stmt, Value * &Result,
                                           bool isFrame) {
      if (!validate_gimple_arglist(stmt, INTEGER_TYPE, VOID_TYPE))
        return false;

      ConstantInt *Level =
          llvm::dyn_cast<ConstantInt>(EmitMemory(gimple_call_arg(stmt, 0)));
      if (!Level) {
        if (isFrame)
          error("invalid argument to %<__builtin_frame_address%>");
        else
          error("invalid argument to %<__builtin_return_address%>");
        return false;
      }

      Intrinsic::ID IID =
          !isFrame ? Intrinsic::returnaddress : Intrinsic::frameaddress;
      Result =
          Builder.CreateCall(Intrinsic::getDeclaration(TheModule, IID), Level);
      Result = Builder.CreateBitCast(
          Result, ConvertType(gimple_call_return_type(stmt)));
      return true;
    }

    bool TreeToLLVM::EmitBuiltinExtractReturnAddr(gimple stmt,
                                                  Value * &Result) {
      Value *Ptr = EmitMemory(gimple_call_arg(stmt, 0));

      // FIXME: Actually we should do something like this:
      //
      // Result = (Ptr & MASK_RETURN_ADDR) + RETURN_ADDR_OFFSET, if mask and
      // offset are defined. This seems to be needed for: ARM, MIPS, Sparc.
      // Unfortunately, these constants are defined as RTL expressions and
      // should be handled separately.

      Result = Builder.CreateBitCast(Ptr, Type::getInt8PtrTy(Context));

      return true;
    }

    bool TreeToLLVM::EmitBuiltinFrobReturnAddr(gimple stmt, Value * &Result) {
      Value *Ptr = EmitMemory(gimple_call_arg(stmt, 0));

      // FIXME: Actually we should do something like this:
      //
      // Result = Ptr - RETURN_ADDR_OFFSET, if offset is defined. This seems to be
      // needed for: MIPS, Sparc.  Unfortunately, these constants are defined
      // as RTL expressions and should be handled separately.

      Result = Builder.CreateBitCast(Ptr, Type::getInt8PtrTy(Context));

      return true;
    }

    bool TreeToLLVM::EmitBuiltinStackSave(gimple stmt, Value * &Result) {
      if (!validate_gimple_arglist(stmt, VOID_TYPE))
        return false;

      Result = Builder.CreateCall(
          Intrinsic::getDeclaration(TheModule, Intrinsic::stacksave));
      return true;
    }

    bool TreeToLLVM::EmitBuiltinUnreachable() {
      Builder.CreateUnreachable();
      return true;
    }

    // Exception handling builtins.

    bool TreeToLLVM::EmitBuiltinEHCopyValues(gimple stmt) {
      unsigned DstRegionNo = tree_low_cst(gimple_call_arg(stmt, 0), 0);
      unsigned SrcRegionNo = tree_low_cst(gimple_call_arg(stmt, 1), 0);
      // Copy the exception pointer.
      Value *ExcPtr = Builder.CreateLoad(getExceptionPtr(SrcRegionNo));
      Builder.CreateStore(ExcPtr, getExceptionPtr(DstRegionNo));
      // Copy the selector value.
      Value *Filter = Builder.CreateLoad(getExceptionFilter(SrcRegionNo));
      Builder.CreateStore(Filter, getExceptionFilter(DstRegionNo));
      return true;
    }

    bool TreeToLLVM::EmitBuiltinEHFilter(gimple stmt, Value * &Result) {
      // Lookup the local that holds the selector value for this region.
      unsigned RegionNo = tree_low_cst(gimple_call_arg(stmt, 0), 0);
      AllocaInst *Filter = getExceptionFilter(RegionNo);
      // Load the selector value out.
      Result = Builder.CreateLoad(Filter);
      // Ensure the returned value has the right integer type.
      tree type = gimple_call_return_type(stmt);
      Result = CastToAnyType(Result, /*isSigned*/ true, getRegType(type),
                             /*isSigned*/ !TYPE_UNSIGNED(type));
      return true;
    }

    bool TreeToLLVM::EmitBuiltinEHPointer(gimple stmt, Value * &Result) {
      // Lookup the local that holds the exception pointer for this region.
      unsigned RegionNo = tree_low_cst(gimple_call_arg(stmt, 0), 0);
      AllocaInst *ExcPtr = getExceptionPtr(RegionNo);
      // Load the exception pointer out.
      Result = Builder.CreateLoad(ExcPtr);
      // Ensure the returned value has the right pointer type.
      tree type = gimple_call_return_type(stmt);
      Result = Builder.CreateBitCast(Result, getRegType(type));
      return true;
    }

// Builtins used by the exception handling runtime.

// On most machines, the CFA coincides with the first incoming parm.
#ifndef ARG_POINTER_CFA_OFFSET
#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET(FNDECL)
#endif

// The mapping from gcc register number to DWARF 2 CFA column number.  By
// default, we just provide columns for all registers.
#ifndef DWARF_FRAME_REGNUM
#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER(REG)
#endif

// Map register numbers held in the call frame info that gcc has
// collected using DWARF_FRAME_REGNUM to those that should be output in
// .debug_frame and .eh_frame.
#ifndef DWARF2_FRAME_REG_OUT
#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO)
#endif

/* Registers that get partially clobbered by a call in a given mode.
   These must not be call used registers.  */
#ifndef HARD_REGNO_CALL_PART_CLOBBERED
#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) 0
#endif

    bool TreeToLLVM::EmitBuiltinDwarfCFA(gimple stmt, Value * &Result) {
      if (!validate_gimple_arglist(stmt, VOID_TYPE))
        return false;

      int cfa_offset = ARG_POINTER_CFA_OFFSET(exp);

      // FIXME: is i32 always enough here?
      Result = Builder.CreateCall(
          Intrinsic::getDeclaration(TheModule, Intrinsic::eh_dwarf_cfa),
          Builder.getInt32(cfa_offset));

      return true;
    }

    bool TreeToLLVM::EmitBuiltinDwarfSPColumn(gimple stmt, Value * &Result) {
      if (!validate_gimple_arglist(stmt, VOID_TYPE))
        return false;

      unsigned int dwarf_regnum = DWARF_FRAME_REGNUM(STACK_POINTER_REGNUM);
      Result = ConstantInt::get(ConvertType(gimple_call_return_type(stmt)),
                                dwarf_regnum);

      return true;
    }

    bool TreeToLLVM::EmitBuiltinEHReturnDataRegno(gimple stmt,
                                                  Value * &Result) {
#ifdef EH_RETURN_DATA_REGNO
      if (!validate_gimple_arglist(stmt, INTEGER_TYPE, VOID_TYPE))
        return false;

      tree which = gimple_call_arg(stmt, 0);
      unsigned HOST_WIDE_INT iwhich;

      if (!isa<INTEGER_CST>(which)) {
        error("argument of %<__builtin_eh_return_regno%> must be constant");
        return false;
      }

      iwhich = tree_low_cst(which, 1);
      iwhich = EH_RETURN_DATA_REGNO(iwhich);
      if (iwhich == INVALID_REGNUM)
        return false;

      iwhich = DWARF_FRAME_REGNUM(iwhich);

      Result =
          ConstantInt::get(ConvertType(gimple_call_return_type(stmt)), iwhich);
#endif

      return true;
    }

    bool TreeToLLVM::EmitBuiltinEHReturn(gimple stmt, Value * &/*Result*/) {
      if (!validate_gimple_arglist(stmt, INTEGER_TYPE, POINTER_TYPE, VOID_TYPE))
        return false;

      Type *IntPtr = DL.getIntPtrType(Context, 0);
      Value *Offset = EmitMemory(gimple_call_arg(stmt, 0));
      Value *Handler = EmitMemory(gimple_call_arg(stmt, 1));

      Intrinsic::ID IID = IntPtr->isIntegerTy(32) ? Intrinsic::eh_return_i32
                                                  : Intrinsic::eh_return_i64;

      Offset = Builder.CreateIntCast(Offset, IntPtr, /*isSigned*/ true);
      Handler = Builder.CreateBitCast(Handler, Type::getInt8PtrTy(Context));

      Value *Args[2] = { Offset, Handler };
      Builder.CreateCall(Intrinsic::getDeclaration(TheModule, IID), Args);
      Builder.CreateUnreachable();
      BeginBlock(BasicBlock::Create(Context));

      return true;
    }

    bool TreeToLLVM::EmitBuiltinInitDwarfRegSizes(gimple stmt,
                                                  Value * &/*Result*/) {
#ifdef DWARF2_UNWIND_INFO
      unsigned int i;
      bool wrote_return_column = false;
      static bool reg_modes_initialized = false;

      if (!validate_gimple_arglist(stmt, POINTER_TYPE, VOID_TYPE))
        return false;

      if (!reg_modes_initialized) {
        init_reg_modes_target();
        reg_modes_initialized = true;
      }

      Value *Addr = Builder.CreateBitCast(EmitMemory(gimple_call_arg(stmt, 0)),
                                          Type::getInt8PtrTy(Context));
      Constant *Size, *Idx;

      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) {
        int rnum = DWARF2_FRAME_REG_OUT(DWARF_FRAME_REGNUM(i), 1);

        if (rnum < DWARF_FRAME_REGISTERS) {
          enum machine_mode save_mode = reg_raw_mode[i];
          HOST_WIDE_INT size;

          if (HARD_REGNO_CALL_PART_CLOBBERED(i, save_mode))
            save_mode = choose_hard_reg_mode(i, 1, true);
          if (DWARF_FRAME_REGNUM(i) == DWARF_FRAME_RETURN_COLUMN) {
            if (save_mode == VOIDmode)
              continue;
            wrote_return_column = true;
          }
          size = GET_MODE_SIZE(save_mode);
          if (rnum < 0)
            continue;

          Size = Builder.getInt8(size);
          Idx = Builder.getInt32(rnum);
          Builder.CreateStore(
              Size,
              Builder.CreateGEP(Addr, Idx, flag_verbose_asm ? "rnum" : ""),
              false);
        }
      }

      if (!wrote_return_column) {
        Size = Builder.getInt8(GET_MODE_SIZE(Pmode));
        Idx = Builder.getInt32(DWARF_FRAME_RETURN_COLUMN);
        Builder.CreateStore(
            Size, Builder.CreateGEP(Addr, Idx, flag_verbose_asm ? "rcol" : ""),
            false);
      }

#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
      Size = Builder.getInt8(GET_MODE_SIZE(Pmode));
      Idx = Builder.getInt32(DWARF_ALT_FRAME_RETURN_COLUMN);
      Builder.CreateStore(
          Size, Builder.CreateGEP(Addr, Idx, flag_verbose_asm ? "acol" : ""),
          false);
#endif

#endif /* DWARF2_UNWIND_INFO */

      // TODO: the RS6000 target needs extra initialization [gcc changeset 122468].

      return true;
    }

    bool TreeToLLVM::EmitBuiltinUnwindInit(gimple stmt, Value * &/*Result*/) {
      if (!validate_gimple_arglist(stmt, VOID_TYPE))
        return false;

      Builder.CreateCall(
          Intrinsic::getDeclaration(TheModule, Intrinsic::eh_unwind_init));

      return true;
    }

    bool TreeToLLVM::EmitBuiltinStackRestore(gimple stmt) {
      if (!validate_gimple_arglist(stmt, POINTER_TYPE, VOID_TYPE))
        return false;

      Value *Ptr = EmitMemory(gimple_call_arg(stmt, 0));
      Ptr = Builder.CreateBitCast(Ptr, Type::getInt8PtrTy(Context));

      Builder.CreateCall(
          Intrinsic::getDeclaration(TheModule, Intrinsic::stackrestore), Ptr);
      return true;
    }

    bool TreeToLLVM::EmitBuiltinAlloca(gimple stmt, Value * &Result) {
      if (!validate_gimple_arglist(stmt, INTEGER_TYPE, VOID_TYPE))
        return false;
      Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
      AllocaInst *Alloca = Builder.CreateAlloca(Type::getInt8Ty(Context), Amt);
      Alloca->setAlignment(BIGGEST_ALIGNMENT / 8);
      Result = Alloca;
      return true;
    }

    bool TreeToLLVM::EmitBuiltinAllocaWithAlign(gimple stmt, Value * &Result) {
      if (!validate_gimple_arglist(stmt, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE))
        return false;
      Value *Amt = EmitMemory(gimple_call_arg(stmt, 0));
      uint64_t Align = getInt64(gimple_call_arg(stmt, 1), true);
      AllocaInst *Alloca = Builder.CreateAlloca(Type::getInt8Ty(Context), Amt);
      Alloca->setAlignment(Align / 8);
      Result = Alloca;
      return true;
    }

#if (GCC_MINOR > 6)
    bool TreeToLLVM::EmitBuiltinAssumeAligned(gimple stmt, Value * &Result) {
      if (!validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
        return false;
      // Return the pointer argument.  TODO: Pass the alignment information on to
      // the optimizers.
      Value *Ptr = EmitRegister(gimple_call_arg(stmt, 0));
      // Bitcast it to the return type.
      Ptr =
          TriviallyTypeConvert(Ptr, getRegType(gimple_call_return_type(stmt)));
      Result = Reg2Mem(Ptr, gimple_call_return_type(stmt), Builder);
      return true;
    }
#endif

    bool TreeToLLVM::EmitBuiltinExpect(gimple stmt, Value * &Result) {
      tree type = gimple_call_return_type(stmt);
      if (gimple_call_num_args(stmt) < 2) {
        Result = Constant::getNullValue(ConvertType(type));
        return true;
      }
      Type *ArgTy = getRegType(type);
      Value *ExpectIntr =
          Intrinsic::getDeclaration(TheModule, Intrinsic::expect, ArgTy);
      Value *ArgValue = EmitRegister(gimple_call_arg(stmt, 0));
      Value *ExpectedValue = EmitRegister(gimple_call_arg(stmt, 1));
      Result = Builder.CreateCall2(ExpectIntr, ArgValue, ExpectedValue);
      Result = Reg2Mem(Result, type, Builder);
      return true;
    }

    bool TreeToLLVM::EmitBuiltinVAStart(gimple stmt) {
      if (gimple_call_num_args(stmt) < 2) {
        error("too few arguments to function %<va_start%>");
        return true;
      }

      tree fntype = TREE_TYPE(current_function_decl);
      if (TYPE_ARG_TYPES(fntype) == 0 ||
          (tree_last(TYPE_ARG_TYPES(fntype)) == void_type_node)) {
        error("%<va_start%> used in function with fixed args");
        return true;
      }

      Constant *va_start =
          Intrinsic::getDeclaration(TheModule, Intrinsic::vastart);
      Value *ArgVal = EmitMemory(gimple_call_arg(stmt, 0));
      ArgVal = Builder.CreateBitCast(ArgVal, Type::getInt8PtrTy(Context));
      Builder.CreateCall(va_start, ArgVal);
      return true;
    }

    bool TreeToLLVM::EmitBuiltinVAEnd(gimple stmt) {
      Value *Arg = EmitMemory(gimple_call_arg(stmt, 0));
      Arg = Builder.CreateBitCast(Arg, Type::getInt8PtrTy(Context));
      Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::vaend),
                         Arg);
      return true;
    }

    bool TreeToLLVM::EmitBuiltinVACopy(gimple stmt) {
      tree Arg1T = gimple_call_arg(stmt, 0);
      tree Arg2T = gimple_call_arg(stmt, 1);

      Value *Arg1 = EmitMemory(Arg1T); // Emit the address of the destination.
      // The second arg of llvm.va_copy is a pointer to a valist.
      Value *Arg2;
      if (!isa<AGGREGATE_TYPE>(va_list_type_node)) {
        // Emit it as a value, then store it to a temporary slot.
        Value *V2 = EmitMemory(Arg2T);
        Arg2 = CreateTemporary(V2->getType());
        Builder.CreateStore(V2, Arg2);
      } else {
        // If the target has aggregate valists, then the second argument
        // from GCC is the address of the source valist and we don't
        // need to do anything special.
        Arg2 = EmitMemory(Arg2T);
      }

      static Type *VPTy = Type::getInt8PtrTy(Context);

      // FIXME: This ignores alignment and volatility of the arguments.
      SmallVector<Value *, 2> Args;
      Args.push_back(Builder.CreateBitCast(Arg1, VPTy));
      Args.push_back(Builder.CreateBitCast(Arg2, VPTy));

      Builder.CreateCall(
          Intrinsic::getDeclaration(TheModule, Intrinsic::vacopy), Args);
      return true;
    }

    bool TreeToLLVM::EmitBuiltinAdjustTrampoline(gimple stmt, Value * &Result) {
      if (!validate_gimple_arglist(stmt, POINTER_TYPE, VOID_TYPE))
        return false;

      Function *Intr =
          Intrinsic::getDeclaration(TheModule, Intrinsic::adjust_trampoline);
      Value *Arg = Builder.CreateBitCast(EmitRegister(gimple_call_arg(stmt, 0)),
                                         Builder.getInt8PtrTy());
      Result = Builder.CreateCall(Intr, Arg);
      return true;
    }

    bool TreeToLLVM::EmitBuiltinInitTrampoline(gimple stmt, bool OnStack) {
      if (!validate_gimple_arglist(stmt, POINTER_TYPE, POINTER_TYPE,
                                   POINTER_TYPE, VOID_TYPE))
        return false;

      Value *Tramp = EmitRegister(gimple_call_arg(stmt, 0));
      Value *Func = EmitRegister(gimple_call_arg(stmt, 1));
      Value *Chain = EmitRegister(gimple_call_arg(stmt, 2));

      Type *VPTy = Builder.getInt8PtrTy();
      Value *Ops[3] = { Builder.CreateBitCast(Tramp, VPTy),
                        Builder.CreateBitCast(Func, VPTy),
                        Builder.CreateBitCast(Chain, VPTy) };

      Function *Intr =
          Intrinsic::getDeclaration(TheModule, Intrinsic::init_trampoline);
      Builder.CreateCall(Intr, Ops);

#if (GCC_MINOR > 5)
      if (OnStack) {
        tree target = TREE_OPERAND(gimple_call_arg(stmt, 1), 0);
        warning_at(DECL_SOURCE_LOCATION(target), OPT_Wtrampolines,
                   "trampoline generated for nested function %qD", target);
      }
#else
      (void)OnStack; // Avoid compiler warning.
#endif

      return true;
    }

    //===----------------------------------------------------------------------===//
    //                      ... Complex Math Expressions ...
    //===----------------------------------------------------------------------===//

    Value *TreeToLLVM::CreateComplex(Value * Real, Value * Imag) {
      assert(Real->getType() == Imag->getType() && "Component type mismatch!");
      Type *EltTy = Real->getType();
      Value *Result = UndefValue::get(StructType::get(EltTy, EltTy, NULL));
      Result = Builder.CreateInsertValue(Result, Real, 0);
      Result = Builder.CreateInsertValue(Result, Imag, 1);
      return Result;
    }

    void TreeToLLVM::SplitComplex(Value * Complex, Value * &Real,
                                  Value * &Imag) {
      Real = Builder.CreateExtractValue(Complex, 0);
      Imag = Builder.CreateExtractValue(Complex, 1);
    }

    //===----------------------------------------------------------------------===//
    //                         ... L-Value Expressions ...
    //===----------------------------------------------------------------------===//

    Value *TreeToLLVM::EmitFieldAnnotation(Value * FieldPtr, tree FieldDecl) {
      tree AnnotateAttr =
          lookup_attribute("annotate", DECL_ATTRIBUTES(FieldDecl));

      Type *SBP = Type::getInt8PtrTy(Context);

      Function *An =
          Intrinsic::getDeclaration(TheModule, Intrinsic::ptr_annotation, SBP);

      // Get file and line number.  FIXME: Should this be for the decl or the
      // use.  Is there a location info for the use?
      Constant *LineNo = ConstantInt::get(Type::getInt32Ty(Context),
                                          DECL_SOURCE_LINE(FieldDecl));
      Constant *File = ConvertMetadataStringToGV(DECL_SOURCE_FILE(FieldDecl));

      File = TheFolder->CreateBitCast(File, SBP);

      // There may be multiple annotate attributes. Pass return of lookup_attr
      //  to successive lookups.
      while (AnnotateAttr) {
        // Each annotate attribute is a tree list.
        // Get value of list which is our linked list of args.
        tree args = TREE_VALUE(AnnotateAttr);

        // Each annotate attribute may have multiple args.
        // Treat each arg as if it were a separate annotate attribute.
        for (tree a = args; a; a = TREE_CHAIN(a)) {
          // Each element of the arg list is a tree list, so get value
          tree val = TREE_VALUE(a);

          // Assert its a string, and then get that string.
          assert(isa<STRING_CST>(val) &&
                 "Annotate attribute arg should always be a string");

          Constant *strGV = AddressOf(val);

          // We can not use the IRBuilder because it will constant fold away
          // the GEP that is critical to distinguish between an annotate
          // attribute on a whole struct from one on the first element of the
          // struct.
          BitCastInst *CastFieldPtr =
              new BitCastInst(FieldPtr, SBP, FieldPtr->getName());
          Builder.Insert(CastFieldPtr);

          Value *Ops[4] = { CastFieldPtr, Builder.CreateBitCast(strGV, SBP),
                            File, LineNo };

          Type *FieldPtrType = FieldPtr->getType();
          FieldPtr = Builder.CreateCall(An, Ops);
          FieldPtr = Builder.CreateBitCast(FieldPtr, FieldPtrType);
        }

        // Get next annotate attribute.
        AnnotateAttr = TREE_CHAIN(AnnotateAttr);
        if (AnnotateAttr)
          AnnotateAttr = lookup_attribute("annotate", AnnotateAttr);
      }
      return FieldPtr;
    }

    LValue TreeToLLVM::EmitLV_ARRAY_REF(tree exp) {
      // The result type is an ElementTy* in the case of an ARRAY_REF, an array
      // of ElementTy in the case of ARRAY_RANGE_REF.

      tree Array = TREE_OPERAND(exp, 0);
      tree ArrayTreeType = TREE_TYPE(Array);
      tree Index = TREE_OPERAND(exp, 1);
      tree IndexType = TREE_TYPE(Index);
      tree ElementType = TREE_TYPE(ArrayTreeType);

      assert(isa<ARRAY_TYPE>(ArrayTreeType) && "Unknown ARRAY_REF!");

      Value *ArrayAddr;
      unsigned ArrayAlign;

      // First subtract the lower bound, if any, in the type of the index.
      Value *IndexVal = EmitRegister(Index);
      tree LowerBound = array_ref_low_bound(exp);
      if (!integer_zerop(LowerBound))
        IndexVal = Builder.CreateSub(
            IndexVal, EmitRegisterWithCast(LowerBound, IndexType), "",
            hasNUW(TREE_TYPE(Index)), hasNSW(TREE_TYPE(Index)));

      LValue ArrayAddrLV = EmitLV(Array);
      assert(!ArrayAddrLV.isBitfield() && "Arrays cannot be bitfields!");
      ArrayAddr = ArrayAddrLV.Ptr;
      ArrayAlign = ArrayAddrLV.getAlignment();

      Type *IntPtrTy = getDataLayout().getIntPtrType(ArrayAddr->getType());
      IndexVal = Builder.CreateIntCast(IndexVal, IntPtrTy,
                                       /*isSigned*/ !TYPE_UNSIGNED(IndexType));

      // If we are indexing over a fixed-size type, just use a GEP.
      if (isSizeCompatible(ElementType)) {
        // Avoid any assumptions about how the array type is represented in LLVM by
        // doing the GEP on a pointer to the first array element.
        Type *EltTy = ConvertType(ElementType);
        ArrayAddr = Builder.CreateBitCast(ArrayAddr, EltTy->getPointerTo());
        StringRef GEPName = flag_verbose_asm ? "ar" : "";
        Value *Ptr = POINTER_TYPE_OVERFLOW_UNDEFINED
                     ? Builder.CreateInBoundsGEP(ArrayAddr, IndexVal, GEPName)
                     : Builder.CreateGEP(ArrayAddr, IndexVal, GEPName);
        unsigned Alignment =
            MinAlign(ArrayAlign, DL.getABITypeAlignment(EltTy));
        return LValue(
            Builder.CreateBitCast(
                Ptr, PointerType::getUnqual(ConvertType(TREE_TYPE(exp)))),
            Alignment);
      }

      // Otherwise, just do raw, low-level pointer arithmetic.  FIXME: this could be
      // much nicer in cases like:
      //   float foo(int w, float A[][w], int g) { return A[g][0]; }

      if (isa<VOID_TYPE>(TREE_TYPE(ArrayTreeType))) {
        ArrayAddr =
            Builder.CreateBitCast(ArrayAddr, Type::getInt8PtrTy(Context));
        StringRef GEPName = flag_verbose_asm ? "va" : "";
        ArrayAddr = POINTER_TYPE_OVERFLOW_UNDEFINED
                    ? Builder.CreateInBoundsGEP(ArrayAddr, IndexVal, GEPName)
                    : Builder.CreateGEP(ArrayAddr, IndexVal, GEPName);
        return LValue(ArrayAddr, 1);
      }

      // FIXME: Might also get here if the element type has constant size, but is
      // humongous.  Add support for this case.
      assert(TREE_OPERAND(exp, 3) &&
             "Size missing for variable sized element!");
      // ScaleFactor is the size of the element type in units divided by (exactly)
      // TYPE_ALIGN_UNIT(ElementType).
      Value *ScaleFactor = Builder.CreateIntCast(
          EmitRegister(TREE_OPERAND(exp, 3)), IntPtrTy, /*isSigned*/ false);
      assert(isPowerOf2_32(TYPE_ALIGN(ElementType)) &&
             "Alignment not a power of two!");
      assert(TYPE_ALIGN(ElementType) >= 8 &&
             "Unit size not a multiple of 8 bits!");
      // ScaleType is chosen to correct for the division in ScaleFactor.
      Type *ScaleType = IntegerType::get(Context, TYPE_ALIGN(ElementType));
      ArrayAddr = Builder.CreateBitCast(ArrayAddr, ScaleType->getPointerTo());

      IndexVal = Builder.CreateMul(IndexVal, ScaleFactor);
      unsigned Alignment = MinAlign(ArrayAlign, TYPE_ALIGN(ElementType) / 8);
      StringRef GEPName = flag_verbose_asm ? "ra" : "";
      Value *Ptr = POINTER_TYPE_OVERFLOW_UNDEFINED
                   ? Builder.CreateInBoundsGEP(ArrayAddr, IndexVal, GEPName)
                   : Builder.CreateGEP(ArrayAddr, IndexVal, GEPName);
      return LValue(
          Builder.CreateBitCast(
              Ptr, PointerType::getUnqual(ConvertType(TREE_TYPE(exp)))),
          Alignment);
    }

    LValue TreeToLLVM::EmitLV_BIT_FIELD_REF(tree exp) {
      LValue Ptr = EmitLV(TREE_OPERAND(exp, 0));
      assert(!Ptr.isBitfield() &&
             "BIT_FIELD_REF operands cannot be bitfields!");

      unsigned BitStart = (unsigned) TREE_INT_CST_LOW(TREE_OPERAND(exp, 2));
      unsigned BitSize = (unsigned) TREE_INT_CST_LOW(TREE_OPERAND(exp, 1));
      Type *ValTy = ConvertType(TREE_TYPE(exp));

      unsigned ValueSizeInBits = DL.getTypeSizeInBits(ValTy);
      assert(BitSize <= ValueSizeInBits &&
             "ValTy isn't large enough to hold the value loaded!");

      assert(ValueSizeInBits == DL.getTypeAllocSizeInBits(ValTy) &&
             "FIXME: BIT_FIELD_REF logic is broken for non-round types");

      // BIT_FIELD_REF values can have BitStart values that are quite large.  We
      // know that the thing we are loading is ValueSizeInBits large.  If BitStart
      // is larger than ValueSizeInBits, bump the pointer over to where it should
      // be.
      if (unsigned UnitOffset = BitStart / ValueSizeInBits) {
        // TODO: If Ptr.Ptr is a struct type or something, we can do much better
        // than this.  e.g. check out when compiling unwind-dw2-fde-darwin.c.
        Ptr.Ptr = Builder.CreateBitCast(Ptr.Ptr, ValTy->getPointerTo());
        Ptr.Ptr = Builder.CreateGEP(Ptr.Ptr, Builder.getInt32(UnitOffset),
                                    flag_verbose_asm ? "bfr" : "");
        unsigned OctetOffset = (UnitOffset * ValueSizeInBits) / 8;
        Ptr.setAlignment(MinAlign(Ptr.getAlignment(), OctetOffset));
        BitStart -= UnitOffset * ValueSizeInBits;
      }

      // If this is referring to the whole field, return the whole thing.
      if (BitStart == 0 && BitSize == ValueSizeInBits) {
        return LValue(Builder.CreateBitCast(Ptr.Ptr, ValTy->getPointerTo()),
                      Ptr.getAlignment());
      }

      return LValue(Builder.CreateBitCast(Ptr.Ptr, ValTy->getPointerTo()), 1,
                    BitStart, BitSize);
    }

    LValue TreeToLLVM::EmitLV_COMPONENT_REF(tree exp) {
      LValue StructAddrLV = EmitLV(TREE_OPERAND(exp, 0));
      tree FieldDecl = TREE_OPERAND(exp, 1);
      unsigned LVAlign = StructAddrLV.getAlignment();

      assert(isa<RECORD_OR_UNION_TYPE>(DECL_CONTEXT(FieldDecl)));

      Type *StructTy = ConvertType(DECL_CONTEXT(FieldDecl));

      assert((!StructAddrLV.isBitfield() || StructAddrLV.BitStart == 0) &&
             "structs cannot be bitfields!");

      StructAddrLV.Ptr =
          Builder.CreateBitCast(StructAddrLV.Ptr, StructTy->getPointerTo());
      Type *FieldTy = ConvertType(TREE_TYPE(FieldDecl));

      // BitStart - This is the actual offset of the field from the start of the
      // struct, in bits.  For bitfields this may be on a non-byte boundary.
      uint64_t FieldBitOffset =
          getInt64(DECL_FIELD_BIT_OFFSET(FieldDecl), true);
      unsigned BitStart;
      Value *FieldPtr;

      // If the GCC field directly corresponds to an LLVM field, handle it.
      unsigned MemberIndex = GetFieldIndex(FieldDecl, StructTy);
      if (MemberIndex < INT_MAX) {
        assert(!TREE_OPERAND(exp, 2) && "Constant not gimple min invariant?");
        // Get a pointer to the byte in which the GCC field starts.
        FieldPtr = Builder.CreateStructGEP(StructAddrLV.Ptr, MemberIndex,
                                           flag_verbose_asm ? "cr" : "");
        // Within that byte, the bit at which the GCC field starts.
        BitStart = FieldBitOffset & 7;
      } else {
        // Offset will hold the field offset in octets.
        Value *Offset;

        if (TREE_OPERAND(exp, 2)) {
          Offset = EmitRegister(TREE_OPERAND(exp, 2));
          // At this point the offset is measured in units divided by (exactly)
          // (DECL_OFFSET_ALIGN / BITS_PER_UNIT).  Convert to octets.
          unsigned factor = DECL_OFFSET_ALIGN(FieldDecl) / 8;
          if (factor != 1)
            Offset = Builder.CreateMul(
                Offset, ConstantInt::get(Offset->getType(), factor));
        } else {
          assert(DECL_FIELD_OFFSET(FieldDecl) && "Field offset not available!");
          Offset = EmitRegister(DECL_FIELD_OFFSET(FieldDecl));
          // At this point the offset is measured in units.  Convert to octets.
          unsigned factor = BITS_PER_UNIT / 8;
          if (factor != 1)
            Offset = Builder.CreateMul(
                Offset, ConstantInt::get(Offset->getType(), factor));
        }

        // Here BitStart gives the offset of the field in bits from Offset.
        BitStart = FieldBitOffset;

        // Incorporate as much of it as possible into the pointer computation.
        unsigned ByteOffset = BitStart / 8;
        if (ByteOffset > 0) {
          Offset = Builder.CreateAdd(
              Offset, ConstantInt::get(Offset->getType(), ByteOffset));
          BitStart -= ByteOffset * 8;
        }

        Type *BytePtrTy = Type::getInt8PtrTy(Context);
        FieldPtr = Builder.CreateBitCast(StructAddrLV.Ptr, BytePtrTy);
        FieldPtr = Builder.CreateInBoundsGEP(FieldPtr, Offset,
                                             flag_verbose_asm ? "rc" : "");
        FieldPtr = Builder.CreateBitCast(FieldPtr, FieldTy->getPointerTo());
      }

      // Compute the alignment of the octet containing the first bit of the field,
      // without assuming that the containing struct itself is properly aligned.
      LVAlign = MinAlign(LVAlign, getFieldAlignment(FieldDecl));

      // If the FIELD_DECL has an annotate attribute on it, emit it.
      if (lookup_attribute("annotate", DECL_ATTRIBUTES(FieldDecl)))
        FieldPtr = EmitFieldAnnotation(FieldPtr, FieldDecl);

      // Make sure we return a pointer to the right type.
      Type *EltTy = ConvertType(TREE_TYPE(exp));
      FieldPtr = Builder.CreateBitCast(FieldPtr, EltTy->getPointerTo());

      if (!isBitfield(FieldDecl)) {
        assert(BitStart == 0 && "Not a bitfield but not at a byte offset!");
        return LValue(FieldPtr, LVAlign);
      }

      assert(BitStart < 8 &&
             "Bit offset not properly incorporated in the pointer");
      assert(DECL_SIZE(FieldDecl) && isa<INTEGER_CST>(DECL_SIZE(FieldDecl)) &&
             "Variable sized bitfield?");
      unsigned BitfieldSize = TREE_INT_CST_LOW(DECL_SIZE(FieldDecl));
      return LValue(FieldPtr, LVAlign, BitStart, BitfieldSize);
    }

    LValue TreeToLLVM::EmitLV_DECL(tree exp) {
      Value *Decl = DEFINITION_LOCAL(exp);
      if (Decl == 0) {
        if (errorcount || sorrycount) {
          Type *Ty = ConvertType(TREE_TYPE(exp));
          PointerType *PTy = Ty->getPointerTo();
          LValue LV(ConstantPointerNull::get(PTy), 1);
          return LV;
        }
        debug_tree(exp);
        llvm_unreachable("Referencing decl that hasn't been laid out!");
      }

      Type *Ty = ConvertType(TREE_TYPE(exp));
      // If we have "extern void foo", make the global have type {} instead of
      // type void.
      if (Ty->isVoidTy())
        Ty = StructType::get(Context);
      PointerType *PTy = Ty->getPointerTo();
      unsigned Alignment = DECL_ALIGN(exp) / 8;
      if (!Alignment)
        Alignment = 1;

      return LValue(Builder.CreateBitCast(Decl, PTy), Alignment);
    }

    LValue TreeToLLVM::EmitLV_INDIRECT_REF(tree exp) {
      // The lvalue is just the address.
      LValue LV =
          LValue(EmitRegister(TREE_OPERAND(exp, 0)), expr_align(exp) / 8);
      // May need to change pointer type, for example when INDIRECT_REF is applied
      // to a void*, resulting in a non-void type.
      LV.Ptr = Builder
          .CreateBitCast(LV.Ptr, ConvertType(TREE_TYPE(exp))->getPointerTo());
      return LV;
    }

#if (GCC_MINOR > 5)
    LValue TreeToLLVM::EmitLV_MEM_REF(tree exp) {
      // The address is the first operand offset in bytes by the second.
      Value *Addr = EmitRegister(TREE_OPERAND(exp, 0));
      if (!integer_zerop(TREE_OPERAND(exp, 1))) {
        // Convert to a byte pointer and displace by the offset.
        Addr = Builder.CreateBitCast(Addr, GetUnitPointerType(Context));
        APInt Offset = getAPIntValue(TREE_OPERAND(exp, 1));
        // The address is always inside the referenced object, so "inbounds".
        Addr =
            Builder.CreateInBoundsGEP(Addr, ConstantInt::get(Context, Offset),
                                      flag_verbose_asm ? "mrf" : "");
      }

      // Ensure the pointer has the right type.
      Addr = Builder.CreateBitCast(Addr, getPointerToType(TREE_TYPE(exp)));

      unsigned Alignment =
#if (GCC_MINOR < 6)
          get_object_alignment(exp, TYPE_ALIGN(TREE_TYPE(exp)),
                               BIGGEST_ALIGNMENT);
#elif(GCC_MINOR < 7)
      std::max(get_object_alignment(exp, BIGGEST_ALIGNMENT),
               TYPE_ALIGN(TREE_TYPE(exp)));
#elif (GCC_MINOR < 8)
      get_object_or_type_alignment(exp);
#else
      get_object_alignment(exp);
#endif
      bool Volatile = TREE_THIS_VOLATILE(exp);

      return LValue(Addr, Alignment / 8, Volatile);
    }
#endif

#if (GCC_MINOR < 6)
    LValue TreeToLLVM::EmitLV_MISALIGNED_INDIRECT_REF(tree exp) {
      // The lvalue is just the address.  The alignment is given by operand 1.
      unsigned Alignment = tree_low_cst(TREE_OPERAND(exp, 1), true);
      // The alignment need not be a power of two, so replace it with the largest
      // power of two that divides it.
      Alignment &= -Alignment;
      if (!Alignment)
        Alignment = 8;
      assert(!(Alignment & 7) && "Alignment not in octets!");
      LValue LV = LValue(EmitRegister(TREE_OPERAND(exp, 0)), Alignment / 8);
      // May need to change pointer type, for example when MISALIGNED_INDIRECT_REF
      // is applied to a void*, resulting in a non-void type.
      LV.Ptr = Builder
          .CreateBitCast(LV.Ptr, ConvertType(TREE_TYPE(exp))->getPointerTo());
      return LV;
    }
#endif

    LValue TreeToLLVM::EmitLV_VIEW_CONVERT_EXPR(tree exp) {
      // The address is the address of the operand.
      LValue LV = EmitLV(TREE_OPERAND(exp, 0));
      // The type is the type of the expression.
      LV.Ptr = Builder
          .CreateBitCast(LV.Ptr, ConvertType(TREE_TYPE(exp))->getPointerTo());
      return LV;
    }

    LValue TreeToLLVM::EmitLV_WITH_SIZE_EXPR(tree exp) {
      // The address is the address of the operand.
      return EmitLV(TREE_OPERAND(exp, 0));
    }

    LValue TreeToLLVM::EmitLV_XXXXPART_EXPR(tree exp, unsigned Idx) {
      LValue Ptr = EmitLV(TREE_OPERAND(exp, 0));
      assert(!Ptr.isBitfield() &&
             "REALPART_EXPR / IMAGPART_EXPR operands cannot be bitfields!");
      unsigned Alignment;
      if (Idx == 0)
        // REALPART alignment is same as the complex operand.
        Alignment = Ptr.getAlignment();
      else
        // IMAGPART alignment = MinAlign(Ptr.Alignment, sizeof field);
        Alignment = MinAlign(Ptr.getAlignment(),
                             DL.getTypeAllocSize(Ptr.Ptr->getType()));
      return LValue(Builder.CreateStructGEP(Ptr.Ptr, Idx,
                                            flag_verbose_asm ? "prtxpr" : ""),
                    Alignment);
    }

    LValue TreeToLLVM::EmitLV_SSA_NAME(tree exp) {
      // TODO: Check the ssa name is being used as an rvalue, see EmitLoadOfLValue.
      Value *Temp = CreateTemporary(ConvertType(TREE_TYPE(exp)));
      Builder.CreateStore(EmitReg_SSA_NAME(exp), Temp);
      return LValue(Temp, 1);
    }

    LValue TreeToLLVM::EmitLV_TARGET_MEM_REF(tree exp) {
      // TODO: Take the address space into account.

      Value *Addr;
      Value *Delta = 0; // Offset from base pointer in units
#if (GCC_MINOR > 5)
      // Starting with gcc 4.6 the address is base + index * step + index2 + offset.
      Addr = EmitRegister(TMR_BASE(exp));
      if (TMR_INDEX2(exp) && !integer_zerop(TMR_INDEX2(exp)))
        Delta = EmitRegister(TMR_INDEX2(exp));
#else
      // In gcc 4.5 the address is &symbol + base + index * step + offset.
      if (TMR_SYMBOL(exp)) {
        Addr = EmitLV(TMR_SYMBOL(exp)).Ptr;
        if (TMR_BASE(exp) && !integer_zerop(TMR_BASE(exp)))
          Delta = EmitRegister(TMR_BASE(exp));
      } else {
        assert(TMR_BASE(exp) && "TARGET_MEM_REF has neither base nor symbol!");
        Addr = EmitRegister(TMR_BASE(exp));
        // The type of BASE is sizetype or a pointer type.  Convert sizetype to i8*.
        if (!isa<PointerType>(Addr->getType()))
          Addr = Builder.CreateIntToPtr(Addr, GetUnitPointerType(Context));
      }
#endif

      if (TMR_INDEX(exp)) {
        Value *Index = EmitRegister(TMR_INDEX(exp));
        if (TMR_STEP(exp) && !integer_onep(TMR_STEP(exp)))
          Index = Builder.CreateMul(Index, EmitRegisterConstant(TMR_STEP(exp)));
        Delta = Delta ? Builder.CreateAdd(Delta, Index) : Index;
      }

      if (TMR_OFFSET(exp) && !integer_zerop(TMR_OFFSET(exp))) {
        Constant *Off =
            ConstantInt::get(Context, getAPIntValue(TMR_OFFSET(exp)));
        Delta = Delta ? Builder.CreateAdd(Delta, Off) : Off;
      }

      if (Delta) {
        // Advance the base pointer by the given number of units.
        Addr = Builder.CreateBitCast(Addr, GetUnitPointerType(Context));
        StringRef GEPName = flag_verbose_asm ? "" : "tmrf";
        Addr = POINTER_TYPE_OVERFLOW_UNDEFINED
               ? Builder.CreateInBoundsGEP(Addr, Delta, GEPName)
               : Builder.CreateGEP(Addr, Delta, GEPName);
      }

      // The result can be of a different pointer type even if we didn't advance it.
      Addr = Builder.CreateBitCast(Addr, getPointerToType(TREE_TYPE(exp)));
      unsigned Alignment =
#if (GCC_MINOR < 6)
          get_object_alignment(exp, TYPE_ALIGN(TREE_TYPE(exp)),
                               BIGGEST_ALIGNMENT);
#elif(GCC_MINOR < 7)
      std::max(get_object_alignment(exp, BIGGEST_ALIGNMENT),
               TYPE_ALIGN(TREE_TYPE(exp)));
#elif (GCC_MINOR < 8)
      get_object_or_type_alignment(exp);
#else
      get_object_alignment(exp);
#endif
      bool Volatile = TREE_THIS_VOLATILE(exp);

      return LValue(Addr, Alignment / 8, Volatile);
    }

    Constant *TreeToLLVM::AddressOfLABEL_DECL(tree exp) {
      return BlockAddress::get(Fn, getLabelDeclBlock(exp));
    }

    //===----------------------------------------------------------------------===//
    //                           ... Emit helpers ...
    //===----------------------------------------------------------------------===//

    /// EmitMinInvariant - The given value is constant in this function.  Return the
    /// corresponding LLVM value.  Only creates code in the entry block.
    Value *TreeToLLVM::EmitMinInvariant(tree reg) {
      Value *V = isa<ADDR_EXPR>(reg) ? EmitInvariantAddress(reg)
                                     : EmitRegisterConstant(reg);
      assert(V->getType() == getRegType(TREE_TYPE(reg)) &&
             "Gimple min invariant has wrong type!");
      return V;
    }

    /// EmitInvariantAddress - The given address is constant in this function.
    /// Return the corresponding LLVM value.  Only creates code in the entry block.
    Value *TreeToLLVM::EmitInvariantAddress(tree addr) {
      assert(is_gimple_invariant_address(addr) &&
             "Expected a locally constant address!");
      assert(is_gimple_reg_type(TREE_TYPE(addr)) && "Not of register type!");

      // Any generated code goes in the entry block.
      BasicBlock *EntryBlock = Fn->begin();

      // Note the current builder position.
      BasicBlock *SavedInsertBB = Builder.GetInsertBlock();
      BasicBlock::iterator SavedInsertPoint = Builder.GetInsertPoint();

      // Pop the entry block terminator.  There may not be a terminator if we are
      // recursing or if the entry block was not yet finished.
      Instruction *Terminator = EntryBlock->getTerminator();
      assert(((SavedInsertBB != EntryBlock && Terminator) ||
              (SavedInsertPoint == EntryBlock->end() && !Terminator)) &&
             "Insertion point doesn't make sense!");
      if (Terminator)
        Terminator->removeFromParent();

      // Point the builder at the end of the entry block.
      Builder.SetInsertPoint(EntryBlock);

      // Calculate the address.
      assert(isa<ADDR_EXPR>(addr) && "Invariant address not ADDR_EXPR!");
      Value *Address = EmitADDR_EXPR(addr);

      // Restore the entry block terminator.
      if (Terminator)
        EntryBlock->getInstList().push_back(Terminator);

      // Restore the builder insertion point.
      if (SavedInsertBB != EntryBlock)
        Builder.SetInsertPoint(SavedInsertBB, SavedInsertPoint);

      assert(Address->getType() == getRegType(TREE_TYPE(addr)) &&
             "Invariant address has wrong type!");
      return Address;
    }

    /// EmitRegisterConstant - Convert the given global constant of register type to
    /// an LLVM constant.  Creates no code, only constants.
    Constant *TreeToLLVM::EmitRegisterConstant(tree reg) {
#ifndef NDEBUG
      if (!is_gimple_constant(reg)) {
        debug_tree(reg);
        llvm_unreachable("Unsupported gimple!");
      }
#endif
      assert(is_gimple_reg_type(TREE_TYPE(reg)) && "Not of register type!");

      switch (TREE_CODE(reg)) {
      default:
        debug_tree(reg);
        llvm_unreachable("Unhandled GIMPLE constant!");

      case INTEGER_CST:
        return EmitIntegerRegisterConstant(reg);
      case REAL_CST:
        return EmitRealRegisterConstant(reg);
        //case FIXED_CST: // Fixed point constant - not yet supported.
        //case STRING_CST: // Allowed by is_gimple_constant, but no known examples.
      case COMPLEX_CST:
        return EmitComplexRegisterConstant(reg);
      case VECTOR_CST:
        return EmitVectorRegisterConstant(reg);
      case CONSTRUCTOR:
        // Vector constant constructors are gimple invariant.  See GCC testcase
        // pr34856.c for an example.
        return EmitConstantVectorConstructor(reg);
      }
    }

    /// EmitRegisterConstantWithCast - Utility that casts the value returned by
    /// EmitRegisterConstant to the given register type.
    Constant *TreeToLLVM::EmitRegisterConstantWithCast(tree reg, tree type) {
      Constant *C = EmitRegisterConstant(reg);
      if (TREE_TYPE(reg) == type)
        return C;
      // For vector types, TYPE_UNSIGNED returns the unsignedness of the element.
      bool SrcIsSigned = !TYPE_UNSIGNED(TREE_TYPE(reg));
      bool DstIsSigned = !TYPE_UNSIGNED(type);
      return CastToAnyType(C, SrcIsSigned, getRegType(type), DstIsSigned);
    }

    /// EncodeExpr - Write the given expression into Buffer as it would appear in
    /// memory on the target (the buffer is resized to contain exactly the bytes
    /// written).  Return the number of bytes written; this can also be obtained
    /// by querying the buffer's size.
    /// The following kinds of expressions are currently supported: INTEGER_CST,
    /// REAL_CST, COMPLEX_CST, VECTOR_CST, STRING_CST.
    static unsigned EncodeExpr(tree exp,
                               SmallVectorImpl<unsigned char> & Buffer) {
      const tree type = TREE_TYPE(exp);
      unsigned SizeInBytes = (TREE_INT_CST_LOW(TYPE_SIZE(type)) + 7) / 8;
      Buffer.resize(SizeInBytes);
      unsigned BytesWritten = native_encode_expr(exp, &Buffer[0], SizeInBytes);
      assert(BytesWritten == SizeInBytes &&
             "Failed to fully encode expression!");
      return BytesWritten;
    }

    /// EmitComplexRegisterConstant - Turn the given COMPLEX_CST into an LLVM
    /// constant of the corresponding register type.
    Constant *TreeToLLVM::EmitComplexRegisterConstant(tree reg) {
      tree elt_type = TREE_TYPE(TREE_TYPE(reg));
      Constant *Elts[2] = {
        EmitRegisterConstantWithCast(TREE_REALPART(reg), elt_type),
        EmitRegisterConstantWithCast(TREE_IMAGPART(reg), elt_type)
      };
      return ConstantStruct::getAnon(Elts);
    }

    /// EmitIntegerRegisterConstant - Turn the given INTEGER_CST into an LLVM
    /// constant of the corresponding register type.
    Constant *TreeToLLVM::EmitIntegerRegisterConstant(tree reg) {
      ConstantInt *CI = ConstantInt::get(Context, getAPIntValue(reg));
      // The destination can be a pointer, integer or floating point type so we need
      // a generalized cast here
      Type *Ty = getRegType(TREE_TYPE(reg));
      Instruction::CastOps opcode = CastInst::getCastOpcode(
          CI, false, Ty, !TYPE_UNSIGNED(TREE_TYPE(reg)));
      return TheFolder->CreateCast(opcode, CI, Ty);
    }

    /// EmitRealRegisterConstant - Turn the given REAL_CST into an LLVM constant
    /// of the corresponding register type.
    Constant *TreeToLLVM::EmitRealRegisterConstant(tree reg) {
      // TODO: Rather than going through memory, construct the APFloat directly from
      // the real_value.  This works fine for zero, inf and nan values, but APFloat
      // has no constructor for normal numbers, i.e. constructing a normal number
      // from the exponent and significand.
      // TODO: Test implementation on a big-endian machine.

      // Encode the constant in Buffer in target format.
      SmallVector<unsigned char, 16> Buffer;
      EncodeExpr(reg, Buffer);

      // Discard any alignment padding, which we assume comes at the end.
      unsigned Precision = TYPE_PRECISION(TREE_TYPE(reg));
      assert((Precision & 7) == 0 && "Unsupported real number precision!");
      Buffer.resize(Precision / 8);

      // We are going to view the buffer as an array of APInt words.  Ensure that
      // the buffer contains a whole number of words by extending it if necessary.
      unsigned Words = (Precision + integerPartWidth - 1) / integerPartWidth;
      // On a little-endian machine extend the buffer by adding bytes to the end.
      Buffer.resize(Words * (integerPartWidth / 8));
      // On a big-endian machine extend the buffer by adding bytes to the beginning.
      if (BYTES_BIG_ENDIAN)
        std::copy_backward(Buffer.begin(), Buffer.begin() + Precision / 8,
                           Buffer.end());

      // Ensure that the least significant word comes first: we are going to make an
      // APInt, and the APInt constructor wants the least significant word first.
      integerPart *Parts = (integerPart *)&Buffer[0];
      if (BYTES_BIG_ENDIAN)
        std::reverse(Parts, Parts + Words);

      Type *Ty = getRegType(TREE_TYPE(reg));
      if (Ty->isPPC_FP128Ty()) {
        // This type is actually a pair of doubles in disguise.  They turn up the
        // wrong way round here, so flip them.
        assert(FLOAT_WORDS_BIG_ENDIAN && "PPC not big endian!");
        assert(Words == 2 && Precision == 128 && "Strange size for PPC_FP128!");
        std::swap(Parts[0], Parts[1]);
      }

      // Form an APInt from the buffer, an APFloat from the APInt, and the desired
      // floating point constant from the APFloat, phew!
      const APInt &I = APInt(Precision, Words, Parts);
      return ConstantFP::get(Context, APFloat(Ty->getFltSemantics(), I));
    }

    /// EmitConstantVectorConstructor - Turn the given constant CONSTRUCTOR into
    /// an LLVM constant of the corresponding vector register type.
    Constant *TreeToLLVM::EmitConstantVectorConstructor(tree reg) {
      // Get the constructor as an LLVM constant.
      Constant *C = ConvertInitializer(reg);
      // Load the vector register out of it.
      return ExtractRegisterFromConstant(C, TREE_TYPE(reg));
    }

    /// EmitVectorRegisterConstant - Turn the given VECTOR_CST into an LLVM constant
    /// of the corresponding register type.
    Constant *TreeToLLVM::EmitVectorRegisterConstant(tree reg) {
      // If there are no elements then immediately return the default value for a
      // small speedup.
#if (GCC_MINOR < 8)
      if (!TREE_VECTOR_CST_ELTS(reg))
#else
      if (!VECTOR_CST_NELTS(reg))
#endif
        return getDefaultValue(getRegType(TREE_TYPE(reg)));

      // Convert the elements.
      SmallVector<Constant *, 16> Elts;
      tree elt_type = TREE_TYPE(TREE_TYPE(reg));
#if (GCC_MINOR < 8)
      for (tree ch = TREE_VECTOR_CST_ELTS(reg); ch; ch = TREE_CHAIN(ch)) {
        tree elt = TREE_VALUE(ch);
#else
      for (unsigned i = 0, e = VECTOR_CST_NELTS(reg); i != e; ++i) {
        tree elt = VECTOR_CST_ELT(reg, i);
#endif
        Elts.push_back(EmitRegisterConstantWithCast(elt, elt_type));
      }

      // If there weren't enough elements then set the rest of the vector to the
      // default value.
      if (Elts.size() < TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg))) {
        Constant *Default = getDefaultValue(getRegType(elt_type));
        Elts.append(TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg)) - Elts.size(),
                    Default);
      }

      return ConstantVector::get(Elts);
    }

    /// VectorHighElements - Return a vector of half the length, consisting of the
    /// elements of the given vector with indices in the top half.
    Value *TreeToLLVM::VectorHighElements(Value * Vec) {
      VectorType *Ty = cast<VectorType>(Vec->getType());
      assert(!(Ty->getNumElements() & 1) &&
             "Vector has odd number of elements!");
      unsigned NumElts = Ty->getNumElements() / 2;
      SmallVector<Constant *, 8> Mask;
      Mask.reserve(NumElts);
      for (unsigned i = 0; i != NumElts; ++i)
        Mask.push_back(Builder.getInt32(NumElts + i));
      return Builder.CreateShuffleVector(Vec, UndefValue::get(Ty),
                                         ConstantVector::get(Mask));
    }

    /// VectorLowElements - Return a vector of half the length, consisting of the
    /// elements of the given vector with indices in the bottom half.
    Value *TreeToLLVM::VectorLowElements(Value * Vec) {
      VectorType *Ty = cast<VectorType>(Vec->getType());
      assert(!(Ty->getNumElements() & 1) &&
             "Vector has odd number of elements!");
      unsigned NumElts = Ty->getNumElements() / 2;
      SmallVector<Constant *, 8> Mask;
      Mask.reserve(NumElts);
      for (unsigned i = 0; i != NumElts; ++i)
        Mask.push_back(Builder.getInt32(i));
      return Builder.CreateShuffleVector(Vec, UndefValue::get(Ty),
                                         ConstantVector::get(Mask));
    }

    //===----------------------------------------------------------------------===//
    //           ... EmitReg* - Convert register expression to LLVM...
    //===----------------------------------------------------------------------===//

    /// EmitMemory - Convert the specified gimple register or local constant of
    /// register type to an LLVM value with in-memory type (given by ConvertType).
    Value *TreeToLLVM::EmitMemory(tree reg) {
      return Reg2Mem(EmitRegister(reg), TREE_TYPE(reg), Builder);
    }

    /// EmitRegister - Convert the specified gimple register or local constant of
    /// register type to an LLVM value.  Only creates code in the entry block.
    Value *TreeToLLVM::EmitRegister(tree reg) {
      while (isa<OBJ_TYPE_REF>(reg))
        reg = OBJ_TYPE_REF_EXPR(reg);
      return isa<SSA_NAME>(reg) ? EmitReg_SSA_NAME(reg) : EmitMinInvariant(reg);
    }

    /// EmitRegisterWithCast - Utility method that calls EmitRegister, then casts
    /// the returned value to the given register type.
    Value *TreeToLLVM::EmitRegisterWithCast(tree reg, tree type) {
      Value *V = EmitRegister(reg);
      if (TREE_TYPE(reg) == type)
        return V;
      // For vector types, TYPE_UNSIGNED returns the unsignedness of the element.
      bool SrcIsSigned = !TYPE_UNSIGNED(TREE_TYPE(reg));
      bool DstIsSigned = !TYPE_UNSIGNED(type);
      return CastToAnyType(V, SrcIsSigned, getRegType(type), DstIsSigned);
    }

    /// EmitReg_SSA_NAME - Return the defining value of the given SSA_NAME.
    /// Only creates code in the entry block.
    Value *TreeToLLVM::EmitReg_SSA_NAME(tree reg) {
      assert(is_gimple_reg_type(TREE_TYPE(reg)) && "Not of register type!");

      // If we already found the definition of the SSA name, return it.
      if (Value *ExistingValue = SSANames[reg]) {
        assert(ExistingValue->getType() == getRegType(TREE_TYPE(reg)) &&
               "SSA name has wrong type!");
        if (!isSSAPlaceholder(ExistingValue))
          return ExistingValue;
      }

      // If this is not the definition of the SSA name, return a placeholder value.
      if (!SSA_NAME_IS_DEFAULT_DEF(reg)) {
        if (Value *ExistingValue = SSANames[reg])
          return ExistingValue; // The type was sanity checked above.
        return SSANames[reg] = GetSSAPlaceholder(getRegType(TREE_TYPE(reg)));
      }

      // This SSA name is the default definition for the underlying symbol.

      // The underlying symbol is an SSA variable.
      tree var = SSA_NAME_VAR(reg);
      assert(SSA_VAR_P(var) && "Not an SSA variable!");

      // If the variable is itself an ssa name, use its LLVM value.
      if (isa<SSA_NAME>(var)) {
        Value *Val = EmitReg_SSA_NAME(var);
        assert(Val->getType() == getRegType(TREE_TYPE(reg)) &&
               "SSA name has wrong type!");
        return DefineSSAName(reg, Val);
      }

      // Otherwise the symbol is a VAR_DECL, PARM_DECL or RESULT_DECL.  Since a
      // default definition is only created if the very first reference to the
      // variable in the function is a read operation, and refers to the value
      // read, it has an undefined value for VAR_DECLs (a RESULT_DECL can have
      // an initial value if the function returns a class by value).
      assert((isa<PARM_DECL>(var) || isa<RESULT_DECL>(var) ||
              isa<VAR_DECL>(var)) && "Unsupported SSA name definition!");
      if (isa<VAR_DECL>(var))
        return DefineSSAName(reg, UndefValue::get(getRegType(TREE_TYPE(reg))));

      // Read the initial value of the parameter and associate it with the ssa name.
      assert(DECL_LOCAL_IF_SET(var) != 0 && "Parameter not laid out?");

      unsigned Alignment = DECL_ALIGN(var) / 8;
      assert(Alignment != 0 && "Parameter with unknown alignment!");

      // Perform the load in the entry block, after all parameters have been set up
      // with their initial values, and before any modifications to their values.

      // Create a builder that inserts code before the SSAInsertionPoint marker.
      LLVMBuilder SSABuilder(Context, Builder.getFolder());
      SSABuilder.SetInsertPoint(SSAInsertionPoint->getParent(),
                                SSAInsertionPoint);

      // Use it to load the parameter value.
      MemRef ParamLoc(DECL_LOCAL_IF_SET(var), Alignment, false);
      Value *Def =
          LoadRegisterFromMemory(ParamLoc, TREE_TYPE(reg), 0, SSABuilder);

      if (flag_verbose_asm)
        NameValue(Def, reg);
      return DefineSSAName(reg, Def);
    }

    // Unary expressions.
    Value *TreeToLLVM::EmitReg_ABS_EXPR(tree op) {
      if (!isa<FLOAT_TYPE>(TREE_TYPE(op))) {
        Value *Op = EmitRegister(op);
        Value *OpN = Builder.CreateNeg(Op, Op->getName() + "neg");
        ICmpInst::Predicate pred =
            TYPE_UNSIGNED(TREE_TYPE(op)) ? ICmpInst::ICMP_UGE
                                         : ICmpInst::ICMP_SGE;
        Value *Cmp = Builder.CreateICmp(
            pred, Op, Constant::getNullValue(Op->getType()), "abscond");
        return Builder.CreateSelect(Cmp, Op, OpN, Op->getName() + "abs");
      }

      if (isa<VECTOR_TYPE>(TREE_TYPE(op))) {
        // Clear the sign bits.
        Value *Op = EmitRegister(op);
        VectorType *VecTy = cast<VectorType>(Op->getType());

        // Mask = ~(1 << (Bits-1)).
        unsigned Bits = VecTy->getElementType()->getPrimitiveSizeInBits();
        Type *IntTy = IntegerType::get(Context, Bits);
        Type *IntVecTy = VectorType::get(IntTy, VecTy->getNumElements());
        APInt API = APInt::getAllOnesValue(Bits);
        API.clearBit(Bits - 1);
        Constant *Mask = ConstantInt::get(IntVecTy, API);

        // Zap the sign bits.
        Op = Builder.CreateBitCast(Op, IntVecTy);
        Op = Builder.CreateAnd(Op, Mask);
        Op = Builder.CreateBitCast(Op, VecTy);
        return Op;
      }

      // Turn FP abs into fabs/fabsf.
      StringRef Name = SelectFPName(TREE_TYPE(op), "fabsf", "fabs", "fabsl");
      if (!Name.empty()) {
        CallInst *Call = EmitSimpleCall(Name, TREE_TYPE(op), op, NULL);
        Call->setDoesNotThrow();
        Call->setDoesNotAccessMemory();
        return Call;
      }

      // Otherwise clear the sign bit.
      Value *Op = EmitRegister(op);
      Type *Ty = Op->getType();

      // Mask = ~(1 << (Bits-1)).
      unsigned Bits = Ty->getPrimitiveSizeInBits();
      Type *IntTy = IntegerType::get(Context, Bits);
      APInt API = APInt::getAllOnesValue(Bits);
      API.clearBit(Bits - 1);
      Constant *Mask = ConstantInt::get(IntTy, API);

      // Zap the sign bit.
      Op = Builder.CreateBitCast(Op, IntTy);
      Op = Builder.CreateAnd(Op, Mask);
      Op = Builder.CreateBitCast(Op, Ty);
      return Op;
    }

    Value *TreeToLLVM::EmitReg_BIT_NOT_EXPR(tree op) {
      Value *Op = EmitRegister(op);
      return Builder.CreateNot(Op, Op->getName() + "not");
    }

    Value *TreeToLLVM::EmitReg_CONJ_EXPR(tree op) {
      tree elt_type = TREE_TYPE(TREE_TYPE(op));
      Value *R, *I;
      SplitComplex(EmitRegister(op), R, I);

      // ~(a+ib) = a + i*-b
      I = CreateAnyNeg(I, elt_type);

      return CreateComplex(R, I);
    }

    Value *TreeToLLVM::EmitReg_CONVERT_EXPR(tree type, tree op) {
      return EmitRegisterWithCast(op, type);
    }

    Value *TreeToLLVM::EmitReg_NEGATE_EXPR(tree op) {
      Value *V = EmitRegister(op);
      tree type = TREE_TYPE(op);

      if (isa<COMPLEX_TYPE>(type)) {
        tree elt_type = TREE_TYPE(type);
        Value *R, *I;
        SplitComplex(V, R, I);

        // -(a+ib) = -a + i*-b
        R = CreateAnyNeg(R, elt_type);
        I = CreateAnyNeg(I, elt_type);

        return CreateComplex(R, I);
      }

      return CreateAnyNeg(V, type);
    }

    Value *TreeToLLVM::EmitReg_PAREN_EXPR(tree op) {
      // TODO: Understand and correctly deal with this subtle expression.
      return EmitRegister(op);
    }

    Value *TreeToLLVM::EmitReg_TRUTH_NOT_EXPR(tree type, tree op) {
      Value *V = EmitRegister(op);
      if (!V->getType()->isIntegerTy(1))
        V = Builder.CreateICmpNE(V, Constant::getNullValue(V->getType()),
                                 "toBool");
      V = Builder.CreateNot(V, V->getName() + "not");
      return Builder.CreateIntCast(V, getRegType(type), /*isSigned*/ false);
    }

    // Comparisons.

    /// EmitCompare - Compare LHS with RHS using the appropriate comparison code.
    /// The result is an i1 boolean.
    Value *TreeToLLVM::EmitCompare(tree lhs, tree rhs, unsigned code) {
      Value *LHS = EmitRegister(lhs);
      Value *RHS = TriviallyTypeConvert(EmitRegister(rhs), LHS->getType());

      // Compute the LLVM opcodes corresponding to the GCC comparison.
      CmpInst::Predicate UIPred = CmpInst::BAD_ICMP_PREDICATE;
      CmpInst::Predicate SIPred = CmpInst::BAD_ICMP_PREDICATE;
      CmpInst::Predicate FPPred = CmpInst::BAD_FCMP_PREDICATE;

      switch (code) {
      default:
        llvm_unreachable("Unhandled condition code!");
      case LT_EXPR:
        UIPred = CmpInst::ICMP_ULT;
        SIPred = CmpInst::ICMP_SLT;
        FPPred = CmpInst::FCMP_OLT;
        break;
      case LE_EXPR:
        UIPred = CmpInst::ICMP_ULE;
        SIPred = CmpInst::ICMP_SLE;
        FPPred = CmpInst::FCMP_OLE;
        break;
      case GT_EXPR:
        UIPred = CmpInst::ICMP_UGT;
        SIPred = CmpInst::ICMP_SGT;
        FPPred = CmpInst::FCMP_OGT;
        break;
      case GE_EXPR:
        UIPred = CmpInst::ICMP_UGE;
        SIPred = CmpInst::ICMP_SGE;
        FPPred = CmpInst::FCMP_OGE;
        break;
      case EQ_EXPR:
        UIPred = SIPred = CmpInst::ICMP_EQ;
        FPPred = CmpInst::FCMP_OEQ;
        break;
      case NE_EXPR:
        UIPred = SIPred = CmpInst::ICMP_NE;
        FPPred = CmpInst::FCMP_UNE;
        break;
      case UNORDERED_EXPR:
        FPPred = CmpInst::FCMP_UNO;
        break;
      case ORDERED_EXPR:
        FPPred = CmpInst::FCMP_ORD;
        break;
      case UNLT_EXPR:
        FPPred = CmpInst::FCMP_ULT;
        break;
      case UNLE_EXPR:
        FPPred = CmpInst::FCMP_ULE;
        break;
      case UNGT_EXPR:
        FPPred = CmpInst::FCMP_UGT;
        break;
      case UNGE_EXPR:
        FPPred = CmpInst::FCMP_UGE;
        break;
      case UNEQ_EXPR:
        FPPred = CmpInst::FCMP_UEQ;
        break;
      case LTGT_EXPR:
        FPPred = CmpInst::FCMP_ONE;
        break;
      }

      if (isa<COMPLEX_TYPE>(TREE_TYPE(lhs))) {
        Value *LHSr, *LHSi;
        SplitComplex(LHS, LHSr, LHSi);
        Value *RHSr, *RHSi;
        SplitComplex(RHS, RHSr, RHSi);

        Value *DSTr, *DSTi;
        if (LHSr->getType()->isFloatingPointTy()) {
          DSTr = Builder.CreateFCmp(FPPred, LHSr, RHSr);
          DSTi = Builder.CreateFCmp(FPPred, LHSi, RHSi);
          if (FPPred == CmpInst::FCMP_OEQ)
            return Builder.CreateAnd(DSTr, DSTi);
          assert(FPPred == CmpInst::FCMP_UNE &&
                 "Unhandled complex comparison!");
          return Builder.CreateOr(DSTr, DSTi);
        }

        assert(SIPred == UIPred && "(In)equality comparison depends on sign!");
        DSTr = Builder.CreateICmp(UIPred, LHSr, RHSr);
        DSTi = Builder.CreateICmp(UIPred, LHSi, RHSi);
        if (UIPred == CmpInst::ICMP_EQ)
          return Builder.CreateAnd(DSTr, DSTi);
        assert(UIPred == CmpInst::ICMP_NE && "Unhandled complex comparison!");
        return Builder.CreateOr(DSTr, DSTi);
      }

      if (LHS->getType()->isFPOrFPVectorTy())
        return Builder.CreateFCmp(FPPred, LHS, RHS);

      // Determine which predicate to use based on signedness.
      CmpInst::Predicate pred = TYPE_UNSIGNED(TREE_TYPE(lhs)) ? UIPred : SIPred;
      return Builder.CreateICmp(pred, LHS, RHS);
    }

    Value *TreeToLLVM::EmitReg_MinMaxExpr(tree op0, tree op1, unsigned UIPred,
                                          unsigned SIPred, unsigned FPPred) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);

      Value *Compare;
      if (isa<FLOAT_TYPE>(TREE_TYPE(op0)))
        Compare = Builder.CreateFCmp(FCmpInst::Predicate(FPPred), LHS, RHS);
      else if (TYPE_UNSIGNED(TREE_TYPE(op0)))
        Compare = Builder.CreateICmp(ICmpInst::Predicate(UIPred), LHS, RHS);
      else
        Compare = Builder.CreateICmp(ICmpInst::Predicate(SIPred), LHS, RHS);

      return Builder.CreateSelect(Compare, LHS, RHS);
    }

    Value *TreeToLLVM::EmitReg_ReducMinMaxExpr(
        tree op, unsigned UIPred, unsigned SIPred, unsigned FPPred) {
      // In the bottom half of the vector, form the max/min of the bottom and top
      // halves of the vector.  Rinse and repeat on the just computed bottom half:
      // in the bottom quarter of the vector, form the max/min of the bottom and
      // top halves of the bottom half.  Continue until only the first element of
      // the vector is computed.  For example, reduc-max <x0, x1, x2, x3> becomes
      //   v = max <x0, x1, undef, undef>, <x2, x3, undef, undef>
      //   w = max <v0, undef, undef, undef>, <v1, undef, undef, undef>
      // where v = <v0, v1, undef, undef>.  The first element of w is the max/min
      // of x0,x1,x2,x3.
      Value *Val = EmitRegister(op);
      Type *Ty = Val->getType();

      CmpInst::Predicate Pred = CmpInst::Predicate(
          isa<FLOAT_TYPE>(TREE_TYPE(op)) ? FPPred : TYPE_UNSIGNED(TREE_TYPE(op))
                                                        ? UIPred
                                                        : SIPred);

      unsigned Length = (unsigned) TYPE_VECTOR_SUBPARTS(TREE_TYPE(op));
      assert(Length > 1 && !(Length & (Length - 1)) &&
             "Length not a power of 2!");
      SmallVector<Constant *, 8> Mask(Length);
      Constant *UndefIndex = UndefValue::get(Type::getInt32Ty(Context));
      for (unsigned Elts = Length >> 1; Elts; Elts >>= 1) {
        // In the extracted vectors, elements with index Elts and on are undefined.
        for (unsigned i = Elts; i != Length; ++i)
          Mask[i] = UndefIndex;
        // Extract elements [0, Elts) from Val.
        for (unsigned i = 0; i != Elts; ++i)
          Mask[i] = Builder.getInt32(i);
        Value *LHS = Builder.CreateShuffleVector(Val, UndefValue::get(Ty),
                                                 ConstantVector::get(Mask));
        // Extract elements [Elts, 2*Elts) from Val.
        for (unsigned i = 0; i != Elts; ++i)
          Mask[i] = Builder.getInt32(Elts + i);
        Value *RHS = Builder.CreateShuffleVector(Val, UndefValue::get(Ty),
                                                 ConstantVector::get(Mask));

        // Replace Val with the max/min of the extracted elements.
        Value *Compare =
            isa<FLOAT_TYPE>(TREE_TYPE(op)) ? Builder.CreateFCmp(Pred, LHS, RHS)
                                           : Builder.CreateICmp(Pred, LHS, RHS);
        Val = Builder.CreateSelect(Compare, LHS, RHS);

        // Repeat, using half as many elements.
      }

      return Val;
    }

    Value *TreeToLLVM::EmitReg_REDUC_PLUS_EXPR(tree op) {
      // In the bottom half of the vector, form the sum of the bottom and top halves
      // of the vector.  Rinse and repeat on the just computed bottom half: in the
      // bottom quarter of the vector, form the sum of the bottom and top halves of
      // the bottom half.  Continue until only the first element of the vector is
      // computed.  For example, reduc-plus <x0, x1, x2, x3> becomes
      //   v = <x0, x1, undef, undef> + <x2, x3, undef, undef>
      //   w = <v0, undef, undef, undef> + <v1, undef, undef, undef>
      // where v = <v0, v1, undef, undef>.  The first element of w is x0+x1+x2+x3.
      Value *Val = EmitRegister(op);
      Type *Ty = Val->getType();

      unsigned Length = (unsigned) TYPE_VECTOR_SUBPARTS(TREE_TYPE(op));
      assert(Length > 1 && !(Length & (Length - 1)) &&
             "Length not a power of 2!");
      SmallVector<Constant *, 8> Mask(Length);
      Constant *UndefIndex = UndefValue::get(Type::getInt32Ty(Context));
      for (unsigned Elts = Length >> 1; Elts; Elts >>= 1) {
        // In the extracted vectors, elements with index Elts and on are undefined.
        for (unsigned i = Elts; i != Length; ++i)
          Mask[i] = UndefIndex;
        // Extract elements [0, Elts) from Val.
        for (unsigned i = 0; i != Elts; ++i)
          Mask[i] = Builder.getInt32(i);
        Value *LHS = Builder.CreateShuffleVector(Val, UndefValue::get(Ty),
                                                 ConstantVector::get(Mask));
        // Extract elements [Elts, 2*Elts) from Val.
        for (unsigned i = 0; i != Elts; ++i)
          Mask[i] = Builder.getInt32(Elts + i);
        Value *RHS = Builder.CreateShuffleVector(Val, UndefValue::get(Ty),
                                                 ConstantVector::get(Mask));

        // Replace Val with the sum of the extracted elements.
        // TODO: Are nsw/nuw flags valid here?
        Val = CreateAnyAdd(LHS, RHS, TREE_TYPE(TREE_TYPE(op)));

        // Repeat, using half as many elements.
      }

      return Val;
    }

    Value *TreeToLLVM::EmitReg_RotateOp(tree type, tree op0, tree op1,
                                        unsigned Opc1, unsigned Opc2) {
      Value *In = EmitRegister(op0);
      Value *Amt = EmitRegister(op1);

      if (Amt->getType() != In->getType())
        Amt = Builder.CreateIntCast(Amt, In->getType(), /*isSigned*/ false,
                                    Amt->getName() + ".cast");

      Value *TypeSize = ConstantInt::get(
          In->getType(), In->getType()->getPrimitiveSizeInBits());

      // Do the two shifts.
      Value *V1 = Builder.CreateBinOp((Instruction::BinaryOps) Opc1, In, Amt);
      Value *OtherShift = Builder.CreateSub(TypeSize, Amt);
      Value *V2 =
          Builder.CreateBinOp((Instruction::BinaryOps) Opc2, In, OtherShift);

      // Or the two together to return them.
      Value *Merge = Builder.CreateOr(V1, V2);
      return Builder.CreateIntCast(Merge, getRegType(type), /*isSigned*/ false);
    }

    Value *TreeToLLVM::EmitReg_ShiftOp(tree op0, tree op1, unsigned Opc) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      // Ensure that the shift amount has the same type as the shiftee.
      if (RHS->getType() != LHS->getType()) {
        if (LHS->getType()->isVectorTy() == RHS->getType()->isVectorTy()) {
          // Scalar shifted by a scalar amount, or a vector shifted by a vector
          // amount.
          assert((!LHS->getType()->isVectorTy() ||
                  cast<VectorType>(LHS->getType())->getNumElements() ==
                  cast<VectorType>(RHS->getType())->getNumElements()) &&
                 "Vector length mismatch!");
          RHS = CastToAnyType(RHS, /*isSigned*/ false, LHS->getType(),
                              /*isSigned*/ false);
        } else {
          // Vector shifted by a scalar amount.  Turn the shift amount into a vector
          // with all elements equal.
          assert(LHS->getType()->isVectorTy() &&
                 "Shifting a scalar by a vector amount!");
          VectorType *VecTy = cast<VectorType>(LHS->getType());
          RHS = CastToAnyType(RHS, /*isSigned*/ false, VecTy->getElementType(),
                              /*isSigned*/ false);
          RHS = Builder.CreateInsertElement(UndefValue::get(VecTy), RHS,
                                            Builder.getInt32(0));
          Type *MaskTy = VectorType::get(Type::getInt32Ty(Context),
                                         VecTy->getNumElements());
          RHS = Builder.CreateShuffleVector(RHS, UndefValue::get(VecTy),
                                            ConstantInt::get(MaskTy, 0));
        }
      }
      return Builder.CreateBinOp((Instruction::BinaryOps) Opc, LHS, RHS);
    }

    Value *TreeToLLVM::EmitReg_VecShiftOp(tree op0, tree op1,
                                          bool isLeftShift) {
      Value *LHS = EmitRegister(op0); // A vector.
      Value *Amt = EmitRegister(op1); // An integer.
      VectorType *VecTy = cast<VectorType>(LHS->getType());
      unsigned Bits = VecTy->getPrimitiveSizeInBits();

      // If the shift is by a multiple of the element size then emit a shuffle.
      if (ConstantInt *CI = llvm::dyn_cast<ConstantInt>(Amt)) {
        // The GCC docs are not clear whether the bits shifted in must be zero or if
        // they can be anything.  Since these expressions are currently only used in
        // situations which make no assumptions about the shifted in bits, we choose
        // to consider them to be undefined since this results in better code.
        unsigned ShiftAmt = (unsigned) CI->getLimitedValue(Bits);
        if (ShiftAmt >= Bits)
          // Shifting by more than the width of the vector is documented as giving
          // an undefined result.
          return UndefValue::get(VecTy);
        unsigned EltBits = VecTy->getElementType()->getPrimitiveSizeInBits();
        if (!(ShiftAmt % EltBits)) {
          // A shift by an integral number of elements.
          unsigned EltOffset =
              ShiftAmt / EltBits; // Shift by this many elements.
          // Shuffle the elements sideways by the appropriate number of elements.
          unsigned Length = VecTy->getNumElements();
          SmallVector<Constant *, 8> Mask;
          Mask.reserve(Length);
          if (isLeftShift) {
            // shl <4 x i32> %v, 32 ->
            // shufflevector <4 x i32> %v, <4 x i32> undef, <undef, 0, 1, 2>
            Mask.append(Length - EltOffset,
                        UndefValue::get(Type::getInt32Ty(Context)));
            for (unsigned i = 0; i != EltOffset; ++i)
              Mask.push_back(Builder.getInt32(i));
          } else {
            // shr <4 x i32> %v, 32 ->
            // shufflevector <4 x i32> %v, <4 x i32> undef, <1, 2, 3, undef>
            for (unsigned i = EltOffset; i != Length; ++i)
              Mask.push_back(Builder.getInt32(i));
            Mask.append(EltOffset, UndefValue::get(Type::getInt32Ty(Context)));
          }
          return Builder.CreateShuffleVector(LHS, UndefValue::get(VecTy),
                                             ConstantVector::get(Mask));
        }
      }

      // Turn the vector into a mighty integer of the same size.
      LHS = Builder.CreateBitCast(LHS, IntegerType::get(Context, Bits));

      // Ensure the shift amount has the same type.
      if (Amt->getType() != LHS->getType())
        Amt = Builder.CreateIntCast(Amt, LHS->getType(), /*isSigned*/ false,
                                    Amt->getName() + ".cast");

      // Perform the shift.
      LHS = Builder.CreateBinOp(
          isLeftShift ? Instruction::Shl : Instruction::LShr, LHS, Amt);

      // Turn the result back into a vector.
      return Builder.CreateBitCast(LHS, VecTy);
    }

    Value *TreeToLLVM::EmitReg_TruthOp(tree type, tree op0, tree op1,
                                       unsigned Opc) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);

      // This is a truth operation like the strict &&,||,^^.  Convert to bool as
      // a test against zero
      LHS = Builder.CreateICmpNE(LHS, Constant::getNullValue(LHS->getType()),
                                 "toBool");
      RHS = Builder.CreateICmpNE(RHS, Constant::getNullValue(RHS->getType()),
                                 "toBool");

      Value *Res = Builder.CreateBinOp((Instruction::BinaryOps) Opc, LHS, RHS);
      return Builder.CreateZExt(Res, getRegType(type));
    }

    Value *TreeToLLVM::EmitReg_CEIL_DIV_EXPR(tree op0, tree op1) {
      // Notation: CEIL_DIV_EXPR <-> CDiv, TRUNC_DIV_EXPR <-> Div.

      // CDiv calculates LHS/RHS by rounding up to the nearest integer.  In terms
      // of Div this means if the values of LHS and RHS have opposite signs or if
      // LHS is zero, then CDiv necessarily equals Div; and
      //   LHS CDiv RHS = (LHS - Sign(RHS)) Div RHS + 1
      // otherwise.

      Type *Ty = getRegType(TREE_TYPE(op0));
      Constant *Zero = ConstantInt::get(Ty, 0);
      Constant *One = ConstantInt::get(Ty, 1);
      Constant *MinusOne = Constant::getAllOnesValue(Ty);

      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);

      if (!TYPE_UNSIGNED(TREE_TYPE(op0))) {
        // In the case of signed arithmetic, we calculate CDiv as follows:
        //   LHS CDiv RHS = (LHS - Sign(RHS) * Offset) Div RHS + Offset,
        // where Offset is 1 if LHS and RHS have the same sign and LHS is
        // not zero, and 0 otherwise.

        // On some machines INT_MIN Div -1 traps.  You might expect a trap for
        // INT_MIN CDiv -1 too, but this implementation will not generate one.
        // Quick quiz question: what value is returned for INT_MIN CDiv -1?

        // Determine the signs of LHS and RHS, and whether they have the same sign.
        Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero);
        Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero);
        Value *HaveSameSign =
            Builder.CreateICmpEQ(LHSIsPositive, RHSIsPositive);

        // Offset equals 1 if LHS and RHS have the same sign and LHS is not zero.
        Value *LHSNotZero = Builder.CreateICmpNE(LHS, Zero);
        Value *OffsetOne = Builder.CreateAnd(HaveSameSign, LHSNotZero);
        // ... otherwise it is 0.
        Value *Offset = Builder.CreateSelect(OffsetOne, One, Zero);

        // Calculate Sign(RHS) ...
        Value *SignRHS = Builder.CreateSelect(RHSIsPositive, One, MinusOne);
        // ... and Sign(RHS) * Offset
        Value *SignedOffset = Builder.CreateSExt(OffsetOne, Ty);
        SignedOffset = Builder.CreateAnd(SignRHS, SignedOffset);

        // Return CDiv = (LHS - Sign(RHS) * Offset) Div RHS + Offset.
        Value *CDiv = Builder.CreateSub(LHS, SignedOffset);
        CDiv = Builder.CreateSDiv(CDiv, RHS);
        return Builder.CreateAdd(CDiv, Offset, "cdiv");
      }

      // In the case of unsigned arithmetic, LHS and RHS necessarily have the
      // same sign, so we can use
      //   LHS CDiv RHS = (LHS - 1) Div RHS + 1
      // as long as LHS is non-zero.

      // Offset is 1 if LHS is non-zero, 0 otherwise.
      Value *LHSNotZero = Builder.CreateICmpNE(LHS, Zero);
      Value *Offset = Builder.CreateSelect(LHSNotZero, One, Zero);

      // Return CDiv = (LHS - Offset) Div RHS + Offset.
      Value *CDiv = Builder.CreateSub(LHS, Offset);
      CDiv = Builder.CreateUDiv(CDiv, RHS);
      return Builder.CreateAdd(CDiv, Offset, "cdiv");
    }

    Value *TreeToLLVM::EmitReg_BIT_AND_EXPR(tree op0, tree op1) {
      Value *LHS = CastToSameSizeInteger(EmitRegister(op0));
      Value *RHS = CastToSameSizeInteger(EmitRegister(op1));
      Value *Res = Builder.CreateAnd(LHS, RHS);
      return CastFromSameSizeInteger(Res, getRegType(TREE_TYPE(op0)));
    }

    Value *TreeToLLVM::EmitReg_BIT_IOR_EXPR(tree op0, tree op1) {
      Value *LHS = CastToSameSizeInteger(EmitRegister(op0));
      Value *RHS = CastToSameSizeInteger(EmitRegister(op1));
      Value *Res = Builder.CreateOr(LHS, RHS);
      return CastFromSameSizeInteger(Res, getRegType(TREE_TYPE(op0)));
    }

    Value *TreeToLLVM::EmitReg_BIT_XOR_EXPR(tree op0, tree op1) {
      Value *LHS = CastToSameSizeInteger(EmitRegister(op0));
      Value *RHS = CastToSameSizeInteger(EmitRegister(op1));
      Value *Res = Builder.CreateXor(LHS, RHS);
      return CastFromSameSizeInteger(Res, getRegType(TREE_TYPE(op0)));
    }

    /// EmitReg_CondExpr - Handle COND_EXPR and VEC_COND_EXPR gimple assign right-
    /// hand sides.
    Value *TreeToLLVM::EmitReg_CondExpr(tree op0, tree op1, tree op2) {
      // The condition is either a comparison or an SSA register.  Note that the
      // reason for accessing tree operands directly rather than taking advantage
      // of COND_EXPR_COND and friends is that the latter fail for VEC_COND_EXPR,
      // which is also handled here.
      Value *CondVal = COMPARISON_CLASS_P(op0)
                       ? EmitCompare(TREE_OPERAND(op0, 0), TREE_OPERAND(op0, 1),
                                     TREE_CODE(op0))
                       : EmitRegister(op0);

      // Ensure the condition has i1 type.
      if (!CondVal->getType()->getScalarType()->isIntegerTy(1))
        CondVal = Builder.CreateICmpNE(
            CondVal, Constant::getNullValue(CondVal->getType()));

      // Emit the true and false values.
      Value *TrueVal = EmitRegister(op1);
      Value *FalseVal = EmitRegister(op2);
      FalseVal = TriviallyTypeConvert(FalseVal, TrueVal->getType());

      // Select the value to use based on the condition.
      return Builder.CreateSelect(CondVal, TrueVal, FalseVal);
    }

    Value *TreeToLLVM::EmitReg_COMPLEX_EXPR(tree op0, tree op1) {
      return CreateComplex(EmitRegister(op0), EmitRegister(op1));
    }

    Value *TreeToLLVM::EmitReg_FLOOR_DIV_EXPR(tree op0, tree op1) {
      // Notation: FLOOR_DIV_EXPR <-> FDiv, TRUNC_DIV_EXPR <-> Div.
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);

      // FDiv calculates LHS/RHS by rounding down to the nearest integer.  In terms
      // of Div this means if the values of LHS and RHS have the same sign or if LHS
      // is zero, then FDiv necessarily equals Div; and
      //   LHS FDiv RHS = (LHS + Sign(RHS)) Div RHS - 1
      // otherwise.

      if (TYPE_UNSIGNED(TREE_TYPE(op0)))
        // In the case of unsigned arithmetic, LHS and RHS necessarily have the
        // same sign, so FDiv is the same as Div.
        return Builder.CreateUDiv(LHS, RHS, "fdiv");

      Type *Ty = getRegType(TREE_TYPE(op0));
      Constant *Zero = ConstantInt::get(Ty, 0);
      Constant *One = ConstantInt::get(Ty, 1);
      Constant *MinusOne = Constant::getAllOnesValue(Ty);

      // In the case of signed arithmetic, we calculate FDiv as follows:
      //   LHS FDiv RHS = (LHS + Sign(RHS) * Offset) Div RHS - Offset,
      // where Offset is 1 if LHS and RHS have opposite signs and LHS is
      // not zero, and 0 otherwise.

      // Determine the signs of LHS and RHS, and whether they have the same sign.
      Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero);
      Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero);
      Value *SignsDiffer = Builder.CreateICmpNE(LHSIsPositive, RHSIsPositive);

      // Offset equals 1 if LHS and RHS have opposite signs and LHS is not zero.
      Value *LHSNotZero = Builder.CreateICmpNE(LHS, Zero);
      Value *OffsetOne = Builder.CreateAnd(SignsDiffer, LHSNotZero);
      // ... otherwise it is 0.
      Value *Offset = Builder.CreateSelect(OffsetOne, One, Zero);

      // Calculate Sign(RHS) ...
      Value *SignRHS = Builder.CreateSelect(RHSIsPositive, One, MinusOne);
      // ... and Sign(RHS) * Offset
      Value *SignedOffset = Builder.CreateSExt(OffsetOne, Ty);
      SignedOffset = Builder.CreateAnd(SignRHS, SignedOffset);

      // Return FDiv = (LHS + Sign(RHS) * Offset) Div RHS - Offset.
      Value *FDiv = Builder.CreateAdd(LHS, SignedOffset);
      FDiv = Builder.CreateSDiv(FDiv, RHS);
      return Builder.CreateSub(FDiv, Offset, "fdiv");
    }

    Value *TreeToLLVM::EmitReg_FLOOR_MOD_EXPR(tree op0, tree op1) {
      // Notation: FLOOR_MOD_EXPR <-> Mod, TRUNC_MOD_EXPR <-> Rem.

      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);

      // We express Mod in terms of Rem as follows: if RHS exactly divides LHS,
      // or the values of LHS and RHS have the same sign, then Mod equals Rem.
      // Otherwise Mod equals Rem + RHS.  This means that LHS Mod RHS traps iff
      // LHS Rem RHS traps.
      if (TYPE_UNSIGNED(TREE_TYPE(op0)))
        // LHS and RHS values must have the same sign if their type is unsigned.
        return Builder.CreateURem(LHS, RHS);

      Type *Ty = getRegType(TREE_TYPE(op0));
      Constant *Zero = ConstantInt::get(Ty, 0);

      // The two possible values for Mod.
      Value *Rem = Builder.CreateSRem(LHS, RHS, "rem");
      Value *RemPlusRHS = Builder.CreateAdd(Rem, RHS);

      // HaveSameSign: (LHS >= 0) == (RHS >= 0).
      Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero);
      Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero);
      Value *HaveSameSign = Builder.CreateICmpEQ(LHSIsPositive, RHSIsPositive);

      // RHS exactly divides LHS iff Rem is zero.
      Value *RemIsZero = Builder.CreateICmpEQ(Rem, Zero);

      Value *SameAsRem = Builder.CreateOr(HaveSameSign, RemIsZero);
      return Builder.CreateSelect(SameAsRem, Rem, RemPlusRHS, "mod");
    }

    Value *TreeToLLVM::EmitReg_MINUS_EXPR(tree op0, tree op1) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      tree type = TREE_TYPE(op0);

      if (isa<COMPLEX_TYPE>(type)) {
        tree elt_type = TREE_TYPE(type);
        Value *LHSr, *LHSi;
        SplitComplex(LHS, LHSr, LHSi);
        Value *RHSr, *RHSi;
        SplitComplex(RHS, RHSr, RHSi);

        // (a+ib) - (c+id) = (a-c) + i(b-d)
        LHSr = CreateAnySub(LHSr, RHSr, elt_type);
        LHSi = CreateAnySub(LHSi, RHSi, elt_type);

        return CreateComplex(LHSr, LHSi);
      }

      return CreateAnySub(LHS, RHS, type);
    }

    Value *TreeToLLVM::EmitReg_MULT_EXPR(tree op0, tree op1) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      tree type = TREE_TYPE(op0);

      if (isa<COMPLEX_TYPE>(type)) {
        tree elt_type = TREE_TYPE(type);
        Value *LHSr, *LHSi;
        SplitComplex(LHS, LHSr, LHSi);
        Value *RHSr, *RHSi;
        SplitComplex(RHS, RHSr, RHSi);
        Value *DSTr, *DSTi;

        // (a+ib) * (c+id) = (ac-bd) + i(ad+cb)
        if (isa<REAL_TYPE>(elt_type)) {
          Value *Tmp1 = Builder.CreateFMul(LHSr, RHSr); // a*c
          Value *Tmp2 = Builder.CreateFMul(LHSi, RHSi); // b*d
          DSTr = Builder.CreateFSub(Tmp1, Tmp2);        // ac-bd

          Value *Tmp3 = Builder.CreateFMul(LHSr, RHSi); // a*d
          Value *Tmp4 = Builder.CreateFMul(RHSr, LHSi); // c*b
          DSTi = Builder.CreateFAdd(Tmp3, Tmp4);        // ad+cb
        } else {
          // If overflow does not wrap in the element type then it is tempting to
          // use NSW operations here.  However that would be wrong since overflow
          // of an intermediate value calculated here does not necessarily imply
          // that the final result overflows.
          Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c
          Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d
          DSTr = Builder.CreateSub(Tmp1, Tmp2);        // ac-bd

          Value *Tmp3 = Builder.CreateMul(LHSr, RHSi); // a*d
          Value *Tmp4 = Builder.CreateMul(RHSr, LHSi); // c*b
          DSTi = Builder.CreateAdd(Tmp3, Tmp4);        // ad+cb
        }

        return CreateComplex(DSTr, DSTi);
      }

      return CreateAnyMul(LHS, RHS, type);
    }

    Value *TreeToLLVM::EmitReg_PLUS_EXPR(tree op0, tree op1) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      tree type = TREE_TYPE(op0);

      if (isa<COMPLEX_TYPE>(type)) {
        tree elt_type = TREE_TYPE(type);
        Value *LHSr, *LHSi;
        SplitComplex(LHS, LHSr, LHSi);
        Value *RHSr, *RHSi;
        SplitComplex(RHS, RHSr, RHSi);

        // (a+ib) + (c+id) = (a+c) + i(b+d)
        LHSr = CreateAnyAdd(LHSr, RHSr, elt_type);
        LHSi = CreateAnyAdd(LHSi, RHSi, elt_type);

        return CreateComplex(LHSr, LHSi);
      }

      return CreateAnyAdd(LHS, RHS, type);
    }

    Value *TreeToLLVM::EmitReg_POINTER_PLUS_EXPR(tree op0, tree op1) {
      Value *Ptr = EmitRegister(op0); // The pointer.
      Value *Idx = EmitRegister(op1); // The offset in units.

      // Convert the pointer into an i8* and add the offset to it.
      Ptr = Builder.CreateBitCast(Ptr, GetUnitPointerType(Context));
      StringRef GEPName = flag_verbose_asm ? "pp" : "";
      return POINTER_TYPE_OVERFLOW_UNDEFINED
             ? Builder.CreateInBoundsGEP(Ptr, Idx, GEPName)
             : Builder.CreateGEP(Ptr, Idx, GEPName);
    }

    Value *TreeToLLVM::EmitReg_RDIV_EXPR(tree op0, tree op1) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      tree type = TREE_TYPE(op0);

      if (isa<COMPLEX_TYPE>(type)) {
        Value *LHSr, *LHSi;
        SplitComplex(LHS, LHSr, LHSi);
        Value *RHSr, *RHSi;
        SplitComplex(RHS, RHSr, RHSi);
        Value *DSTr, *DSTi;

        // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
        assert(isa<REAL_TYPE>(TREE_TYPE(type)) &&
               "RDIV_EXPR not floating point!");
        Value *Tmp1 = Builder.CreateFMul(LHSr, RHSr); // a*c
        Value *Tmp2 = Builder.CreateFMul(LHSi, RHSi); // b*d
        Value *Tmp3 = Builder.CreateFAdd(Tmp1, Tmp2); // ac+bd

        Value *Tmp4 = Builder.CreateFMul(RHSr, RHSr); // c*c
        Value *Tmp5 = Builder.CreateFMul(RHSi, RHSi); // d*d
        Value *Tmp6 = Builder.CreateFAdd(Tmp4, Tmp5); // cc+dd
        DSTr = Builder.CreateFDiv(Tmp3, Tmp6);

        Value *Tmp7 = Builder.CreateFMul(LHSi, RHSr); // b*c
        Value *Tmp8 = Builder.CreateFMul(LHSr, RHSi); // a*d
        Value *Tmp9 = Builder.CreateFSub(Tmp7, Tmp8); // bc-ad
        DSTi = Builder.CreateFDiv(Tmp9, Tmp6);

        return CreateComplex(DSTr, DSTi);
      }

      assert(isa<FLOAT_TYPE>(type) && "RDIV_EXPR not floating point!");
      return Builder.CreateFDiv(LHS, RHS);
    }

    Value *TreeToLLVM::EmitReg_ROUND_DIV_EXPR(tree op0, tree op1) {
      // Notation: ROUND_DIV_EXPR <-> RDiv, TRUNC_DIV_EXPR <-> Div.

      // RDiv calculates LHS/RHS by rounding to the nearest integer.  Ties
      // are broken by rounding away from zero.  In terms of Div this means:
      //   LHS RDiv RHS = (LHS + (RHS Div 2)) Div RHS
      // if the values of LHS and RHS have the same sign; and
      //   LHS RDiv RHS = (LHS - (RHS Div 2)) Div RHS
      // if the values of LHS and RHS differ in sign.  The intermediate
      // expressions in these formulae can overflow, so some tweaking is
      // required to ensure correct results.  The details depend on whether
      // we are doing signed or unsigned arithmetic.

      Type *Ty = getRegType(TREE_TYPE(op0));
      Constant *Zero = ConstantInt::get(Ty, 0);
      Constant *Two = ConstantInt::get(Ty, 2);

      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);

      if (!TYPE_UNSIGNED(TREE_TYPE(op0))) {
        // In the case of signed arithmetic, we calculate RDiv as follows:
        //   LHS RDiv RHS = (sign) ( (|LHS| + (|RHS| UDiv 2)) UDiv |RHS| ),
        // where sign is +1 if LHS and RHS have the same sign, -1 if their
        // signs differ.  Doing the computation unsigned ensures that there
        // is no overflow.

        // On some machines INT_MIN Div -1 traps.  You might expect a trap for
        // INT_MIN RDiv -1 too, but this implementation will not generate one.
        // Quick quiz question: what value is returned for INT_MIN RDiv -1?

        // Determine the signs of LHS and RHS, and whether they have the same sign.
        Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero);
        Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero);
        Value *HaveSameSign =
            Builder.CreateICmpEQ(LHSIsPositive, RHSIsPositive);

        // Calculate |LHS| ...
        Value *MinusLHS = Builder.CreateNeg(LHS);
        Value *AbsLHS = Builder.CreateSelect(LHSIsPositive, LHS, MinusLHS,
                                             LHS->getName() + ".abs");
        // ... and |RHS|
        Value *MinusRHS = Builder.CreateNeg(RHS);
        Value *AbsRHS = Builder.CreateSelect(RHSIsPositive, RHS, MinusRHS,
                                             RHS->getName() + ".abs");

        // Calculate AbsRDiv = (|LHS| + (|RHS| UDiv 2)) UDiv |RHS|.
        Value *HalfAbsRHS = Builder.CreateUDiv(AbsRHS, Two);
        Value *Numerator = Builder.CreateAdd(AbsLHS, HalfAbsRHS);
        Value *AbsRDiv = Builder.CreateUDiv(Numerator, AbsRHS);

        // Return AbsRDiv or -AbsRDiv according to whether LHS and RHS have the
        // same sign or not.
        Value *MinusAbsRDiv = Builder.CreateNeg(AbsRDiv);
        return Builder.CreateSelect(HaveSameSign, AbsRDiv, MinusAbsRDiv,
                                    "rdiv");
      }

      // In the case of unsigned arithmetic, LHS and RHS necessarily have the
      // same sign, however overflow is a problem.  We want to use the formula
      //   LHS RDiv RHS = (LHS + (RHS Div 2)) Div RHS,
      // but if LHS + (RHS Div 2) overflows then we get the wrong result.  Since
      // the use of a conditional branch seems to be unavoidable, we choose the
      // simple solution of explicitly checking for overflow, and using
      //   LHS RDiv RHS = ((LHS + (RHS Div 2)) - RHS) Div RHS + 1
      // if it occurred.

      // Usually the numerator is LHS + (RHS Div 2); calculate this.
      Value *HalfRHS = Builder.CreateUDiv(RHS, Two);
      Value *Numerator = Builder.CreateAdd(LHS, HalfRHS);

      // Did the calculation overflow?
      Value *Overflowed = Builder.CreateICmpULT(Numerator, HalfRHS);

      // If so, use (LHS + (RHS Div 2)) - RHS for the numerator instead.
      Value *AltNumerator = Builder.CreateSub(Numerator, RHS);
      Numerator = Builder.CreateSelect(Overflowed, AltNumerator, Numerator);

      // Quotient = Numerator / RHS.
      Value *Quotient = Builder.CreateUDiv(Numerator, RHS);

      // Return Quotient unless we overflowed, in which case return Quotient + 1.
      return Builder.CreateAdd(
          Quotient, Builder.CreateIntCast(Overflowed, Ty, /*isSigned*/ false),
          "rdiv");
    }

    Value *TreeToLLVM::EmitReg_TRUNC_DIV_EXPR(tree op0, tree op1,
                                              bool isExact) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      tree type = TREE_TYPE(op0);

      if (isa<COMPLEX_TYPE>(type)) {
        tree elt_type = TREE_TYPE(type);
        Value *LHSr, *LHSi;
        SplitComplex(LHS, LHSr, LHSi);
        Value *RHSr, *RHSi;
        SplitComplex(RHS, RHSr, RHSi);
        Value *DSTr, *DSTi;

        // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd))
        assert(LHSr->getType()->isIntegerTy() && "TRUNC_DIV_EXPR not integer!");
        // If overflow does not wrap in the element type then it is tempting to
        // use NSW operations here.  However that would be wrong since overflow
        // of an intermediate value calculated here does not necessarily imply
        // that the final result overflows.
        Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c
        Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d
        Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2); // ac+bd

        Value *Tmp4 = Builder.CreateMul(RHSr, RHSr); // c*c
        Value *Tmp5 = Builder.CreateMul(RHSi, RHSi); // d*d
        Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5); // cc+dd
        DSTr = TYPE_UNSIGNED(elt_type) ? Builder.CreateUDiv(Tmp3, Tmp6)
                                       : Builder.CreateSDiv(Tmp3, Tmp6);

        Value *Tmp7 = Builder.CreateMul(LHSi, RHSr); // b*c
        Value *Tmp8 = Builder.CreateMul(LHSr, RHSi); // a*d
        Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8); // bc-ad
        DSTi = TYPE_UNSIGNED(elt_type) ? Builder.CreateUDiv(Tmp9, Tmp6)
                                       : Builder.CreateSDiv(Tmp9, Tmp6);

        return CreateComplex(DSTr, DSTi);
      }

      assert(LHS->getType()->isIntOrIntVectorTy() &&
             "TRUNC_DIV_EXPR not integer!");
      if (TYPE_UNSIGNED(type))
        return Builder.CreateUDiv(LHS, RHS, "", isExact);
      else
        return Builder.CreateSDiv(LHS, RHS, "", isExact);
    }

    Value *TreeToLLVM::EmitReg_TRUNC_MOD_EXPR(tree op0, tree op1) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      return TYPE_UNSIGNED(TREE_TYPE(op0)) ? Builder.CreateURem(LHS, RHS)
                                           : Builder.CreateSRem(LHS, RHS);
    }

#if (GCC_MINOR < 7)
    Value *TreeToLLVM::EmitReg_VEC_EXTRACT_EVEN_EXPR(tree op0, tree op1) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      unsigned Length = (unsigned) TYPE_VECTOR_SUBPARTS(TREE_TYPE(op0));
      SmallVector<Constant *, 16> Mask;
      Mask.reserve(Length);
      for (unsigned i = 0; i != Length; ++i)
        Mask.push_back(Builder.getInt32(2 * i));
      return Builder.CreateShuffleVector(LHS, RHS, ConstantVector::get(Mask));
    }
#endif

#if (GCC_MINOR < 7)
    Value *TreeToLLVM::EmitReg_VEC_EXTRACT_ODD_EXPR(tree op0, tree op1) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      unsigned Length = (unsigned) TYPE_VECTOR_SUBPARTS(TREE_TYPE(op0));
      SmallVector<Constant *, 16> Mask;
      Mask.reserve(Length);
      for (unsigned i = 0; i != Length; ++i)
        Mask.push_back(Builder.getInt32(2 * i + 1));
      return Builder.CreateShuffleVector(LHS, RHS, ConstantVector::get(Mask));
    }
#endif

#if (GCC_MINOR < 7)
    Value *TreeToLLVM::EmitReg_VEC_INTERLEAVE_HIGH_EXPR(tree op0, tree op1) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      unsigned Length = (unsigned) TYPE_VECTOR_SUBPARTS(TREE_TYPE(op0));
      assert(!(Length & 1) && "Expected an even number of vector elements!");
      SmallVector<Constant *, 16> Mask;
      Mask.reserve(Length);
      for (unsigned i = Length / 2; i != Length; ++i) {
        Mask.push_back(Builder.getInt32(i));
        Mask.push_back(Builder.getInt32(Length + i));
      }
      return Builder.CreateShuffleVector(LHS, RHS, ConstantVector::get(Mask));
    }
#endif

#if (GCC_MINOR < 7)
    Value *TreeToLLVM::EmitReg_VEC_INTERLEAVE_LOW_EXPR(tree op0, tree op1) {
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);
      unsigned Length = (unsigned) TYPE_VECTOR_SUBPARTS(TREE_TYPE(op0));
      assert(!(Length & 1) && "Expected an even number of vector elements!");
      SmallVector<Constant *, 16> Mask;
      Mask.reserve(Length);
      for (unsigned i = 0, e = Length / 2; i != e; ++i) {
        Mask.push_back(Builder.getInt32(i));
        Mask.push_back(Builder.getInt32(Length + i));
      }
      return Builder.CreateShuffleVector(LHS, RHS, ConstantVector::get(Mask));
    }
#endif

    Value *TreeToLLVM::EmitReg_VEC_PACK_TRUNC_EXPR(tree type, tree op0,
                                                   tree op1) {
      // Eg: <4 x float> = VEC_PACK_TRUNC_EXPR(<2 x double>, <2 x double>)
      // or <4 x i32> = VEC_PACK_FIX_TRUNC_EXPR(<2 x double>, <2 x double>).
      Value *LHS = EmitRegister(op0);
      Value *RHS = EmitRegister(op1);

      // Truncate the input elements to the output element type, eg: <2 x double>
      // -> <2 x float>.
      unsigned Length = (unsigned) TYPE_VECTOR_SUBPARTS(TREE_TYPE(op0));
      Type *DestTy = VectorType::get(getRegType(TREE_TYPE(type)), Length);
      LHS = CastToAnyType(LHS, !TYPE_UNSIGNED(TREE_TYPE(TREE_TYPE(op0))),
                          DestTy, !TYPE_UNSIGNED(TREE_TYPE(type)));
      RHS = CastToAnyType(RHS, !TYPE_UNSIGNED(TREE_TYPE(TREE_TYPE(op0))),
                          DestTy, !TYPE_UNSIGNED(TREE_TYPE(type)));

      // Concatenate the truncated inputs into one vector of twice the length,
      // eg: <2 x float>, <2 x float> -> <4 x float>.
      SmallVector<Constant *, 16> Mask;
      Mask.reserve(2 * Length);
      for (unsigned i = 0, e = 2 * Length; i != e; ++i)
        Mask.push_back(Builder.getInt32(i));
      return Builder.CreateShuffleVector(LHS, RHS, ConstantVector::get(Mask));
    }

#if (GCC_MINOR > 6)
    Value *TreeToLLVM::EmitReg_VEC_PERM_EXPR(tree op0, tree op1, tree op2) {
      unsigned Length = (unsigned) TYPE_VECTOR_SUBPARTS(TREE_TYPE(op0));

      // The vectors to shuffle.
      Value *V0 = EmitRegister(op0);
      Value *V1 = EmitRegister(op1);

      // The shuffle mask.
      Value *Mask = EmitRegister(op2);

      // The GCC semantics are that mask indices off the end are wrapped back into
      // range, so reduce the mask modulo 2*Length.
      assert(!(Length & (Length - 1)) && "Vector length not a power of two!");
      Mask = Builder.CreateAnd(
          Mask, ConstantInt::get(Mask->getType(), 2 * Length - 1));

      // Convert to a vector of i32, as required by the shufflevector instruction.
      Type *MaskTy = VectorType::get(Builder.getInt32Ty(), Length);
      tree mask_elt_type = TREE_TYPE(TREE_TYPE(op2));
      Value *Mask32 =
          Builder.CreateIntCast(Mask, MaskTy, !TYPE_UNSIGNED(mask_elt_type));

      // Use a shufflevector instruction if this directly corresponds to one, i.e.
      // if the mask is a vector of constant integers or undef.
      if (ShuffleVectorInst::isValidOperands(V0, V1, Mask32))
        return Builder.CreateShuffleVector(V0, V1, Mask32);

      // Store the vectors to successive memory locations in a temporary.
      tree elt_type = TREE_TYPE(TREE_TYPE(op0));
      Type *EltTy = ConvertType(elt_type);
      unsigned Align = DL.getABITypeAlignment(EltTy);
      // The temporary is a struct containing the pair of input vectors.
      Type *TmpTy = StructType::get(ConvertType(TREE_TYPE(op0)),
                                    ConvertType(TREE_TYPE(op1)), NULL);
      AllocaInst *Tmp = CreateTemporary(TmpTy, Align);
      // Store the first vector to the first element of the pair.
      Value *Tmp0 =
          Builder.CreateStructGEP(Tmp, 0, flag_verbose_asm ? "vp1s" : "");
      StoreRegisterToMemory(V0, MemRef(Tmp0, Align, /*Volatile*/ false),
                            TREE_TYPE(op0), 0, Builder);
      // Store the second vector to the second element of the pair.
      Value *Tmp1 =
          Builder.CreateStructGEP(Tmp, 1, flag_verbose_asm ? "vp2s" : "");
      StoreRegisterToMemory(V1, MemRef(Tmp1, Align, /*Volatile*/ false),
                            TREE_TYPE(op1), 0, Builder);

      // Load out the components according to the mask.
      Value *Result = UndefValue::get(V0->getType());
      Value *BaseAddr = Builder.CreateBitCast(Tmp, EltTy->getPointerTo());
      for (unsigned i = 0; i != Length; ++i) {
        // Extract from the mask the index of the element to load.
        Value *MaskIdx = Builder.getInt32(i);
        Value *Idx = Builder.CreateExtractElement(Mask, MaskIdx);
        // Advance that many elements from the start of the temporary and load it.
        Value *Ptr = Builder.CreateInBoundsGEP(BaseAddr, Idx,
                                               flag_verbose_asm ? "vpl" : "");
        Value *Elt = LoadRegisterFromMemory(MemRef(Ptr, Align, false), elt_type,
                                            0, Builder);
        // Insert it into the result.
        Result = Builder.CreateInsertElement(Result, Elt, MaskIdx);
      }
      return Result;
    }
#endif

#if (GCC_MINOR > 5)
    Value *TreeToLLVM::EmitReg_FMA_EXPR(tree op0, tree op1, tree op2) {
      Value *V0 = EmitRegister(op0);
      Value *V1 = EmitRegister(op1);
      Value *V2 = EmitRegister(op2);

      Value *FMAIntr = Intrinsic::getDeclaration(TheModule, Intrinsic::fma,
                                                 V0->getType());
      return Builder.CreateCall3(FMAIntr, V0, V1, V2);
    }
#endif

    Value *TreeToLLVM::EmitReg_VecUnpackHiExpr(tree type, tree op0) {
      // Eg: <2 x double> = VEC_UNPACK_HI_EXPR(<4 x float>)
      Value *Op = EmitRegister(op0);

      // Extract the high elements, eg: <4 x float> -> <2 x float>.
      Op = VectorHighElements(Op);

      // Extend the input elements to the output element type, eg: <2 x float>
      // -> <2 x double>.
      Type *DestTy = getRegType(type);
      return CastToAnyType(Op, !TYPE_UNSIGNED(TREE_TYPE(TREE_TYPE(op0))),
                           DestTy, !TYPE_UNSIGNED(TREE_TYPE(type)));
    }

    Value *TreeToLLVM::EmitReg_VecUnpackLoExpr(tree type, tree op0) {
      // Eg: <2 x double> = VEC_UNPACK_LO_EXPR(<4 x float>)
      Value *Op = EmitRegister(op0);

      // Extract the low elements, eg: <4 x float> -> <2 x float>.
      Op = VectorLowElements(Op);

      // Extend the input elements to the output element type, eg: <2 x float>
      // -> <2 x double>.
      Type *DestTy = getRegType(type);
      return CastToAnyType(Op, !TYPE_UNSIGNED(TREE_TYPE(TREE_TYPE(op0))),
                           DestTy, !TYPE_UNSIGNED(TREE_TYPE(type)));
    }

    Value *TreeToLLVM::EmitReg_VEC_WIDEN_MULT_HI_EXPR(tree type, tree op0,
                                                      tree op1) {
      Value *Hi0 = EmitReg_VecUnpackHiExpr(type, op0);
      Value *Hi1 = EmitReg_VecUnpackHiExpr(type, op1);
      return Builder.CreateMul(Hi0, Hi1);
    }

    Value *TreeToLLVM::EmitReg_VEC_WIDEN_MULT_LO_EXPR(tree type, tree op0,
                                                      tree op1) {
      Value *Lo0 = EmitReg_VecUnpackLoExpr(type, op0);
      Value *Lo1 = EmitReg_VecUnpackLoExpr(type, op1);
      return Builder.CreateMul(Lo0, Lo1);
    }

    Value *TreeToLLVM::EmitReg_WIDEN_MULT_EXPR(tree type, tree op0, tree op1) {
      Value *LHS = EmitRegisterWithCast(op0, type);
      Value *RHS = EmitRegisterWithCast(op1, type);
      return Builder.CreateMul(LHS, RHS);
    }

    //===----------------------------------------------------------------------===//
    //                        ... Exception Handling ...
    //===----------------------------------------------------------------------===//

    //===----------------------------------------------------------------------===//
    //                  ... Render* - Convert GIMPLE to LLVM ...
    //===----------------------------------------------------------------------===//

    void TreeToLLVM::RenderGIMPLE_ASM(gimple stmt) {
      // A gimple asm statement consists of an asm string, a list of outputs, a list
      // of inputs, a list of clobbers, a list of labels and a "volatile" flag.
      // These correspond directly to the elements of an asm statement.  For example
      //   asm ("combine %2,%0" : "=r" (x) : "0" (x), "g" (y));
      // Here the asm string is "combine %2,%0" and can be obtained as a const char*
      // by calling gimple_asm_string.  The only output is "=r" (x).  The number of
      // outputs is given by gimple_asm_noutputs, 1 in this case, and the outputs
      // themselves can be obtained by calling gimple_asm_output_op.  This returns a
      // TREE_LIST node with an SSA name for "x" as the TREE_VALUE; the TREE_PURPOSE
      // is also a TREE_LIST with TREE_VALUE a string constant holding "=r".  There
      // are two inputs, "0" (x) and "g" (y), so gimple_asm_ninputs returns 2.  The
      // routine gimple_asm_input_op returns them in the same format as for outputs.
      // The number of clobbers is returned by gimple_asm_nclobbers, 0 in this case.
      // To get the clobbers use gimple_asm_clobber_op.  This returns a TREE_LIST
      // node with TREE_VALUE a string constant holding the clobber.  To find out if
      // the asm is volatile call gimple_asm_volatile_p, which returns true if so.
      // See below for labels (this example does not have any).

      // Note that symbolic names have been substituted before getting here.  For
      // example this
      //   asm ("cmoveq %1,%2,%[result]" : [result] "=r"(result)
      //        : "r"(test), "r"(new), "[result]"(old));
      // turns up as
      //   asm ("cmoveq %1,%2,%0" : "=r"(result) : "r"(test), "r"(new), "0"(old));

      // Note that clobbers may not turn up in the same order as in the original, eg
      //   asm volatile ("movc3 %0,%1,%2" : /* no outputs */
      //                 : "g" (from), "g" (to), "g" (count)
      //                 : "r0", "r1", "r2", "r3", "r4", "r5");
      // The clobbers turn up as "r5", "r4", "r3", "r2", "r1", "r0".

      // Here is an example of the "asm goto" construct (not yet supported by LLVM):
      //   int frob(int x) {
      //     int y;
      //     asm goto ("frob %%r5, %1; jc %l[error]; mov (%2), %%r5"
      //               : : "r"(x), "r"(&y) : "r5", "memory" : error);
      //     return y;
      //   error:
      //     return -1;
      //   }
      // The number of labels, one in this case, is returned by gimple_asm_nlabels.
      // The labels themselves are returned by gimple_asm_label_op as a TREE_LIST
      // node with TREE_PURPOSE a string constant holding the label name ("error")
      // and TREE_VALUE holding the appropriate LABEL_DECL.

      // TODO: Add support for labels.
      if (gimple_asm_nlabels(stmt) > 0) {
        sorry("'asm goto' not supported");
        return;
      }

      const unsigned NumOutputs = gimple_asm_noutputs(stmt);
      const unsigned NumInputs = gimple_asm_ninputs(stmt);
      const unsigned NumClobbers = gimple_asm_nclobbers(stmt);

      /// Constraints - The output/input constraints, concatenated together in array
      /// form instead of list form.  This way of doing things is forced on us by
      /// GCC routines like parse_output_constraint which rummage around inside the
      /// array.
      const char **Constraints = (const char **)alloca(
          (NumOutputs + NumInputs) * sizeof(const char *));

      // Initialize the Constraints array.
      for (unsigned i = 0; i != NumOutputs; ++i) {
        tree Output = gimple_asm_output_op(stmt, i);
        // If there's an erroneous arg then bail out.
        if (TREE_TYPE(TREE_VALUE(Output)) == error_mark_node)
          return;
        // Record the output constraint.
        const char *Constraint =
            TREE_STRING_POINTER(TREE_VALUE(TREE_PURPOSE(Output)));
        Constraints[i] = Constraint;
      }
      for (unsigned i = 0; i != NumInputs; ++i) {
        tree Input = gimple_asm_input_op(stmt, i);
        // If there's an erroneous arg then bail out.
        if (TREE_TYPE(TREE_VALUE(Input)) == error_mark_node)
          return;
        // Record the input constraint.
        const char *Constraint =
            TREE_STRING_POINTER(TREE_VALUE(TREE_PURPOSE(Input)));
        Constraints[NumOutputs + i] = Constraint;
      }

      // Look for multiple alternative constraints: multiple alternatives separated
      // by commas.
      unsigned NumChoices = 0; // sentinal; real value is always at least 1.
      for (unsigned i = 0; i != NumInputs; ++i) {
        tree Input = gimple_asm_input_op(stmt, i);
        unsigned NumInputChoices = 1;
        for (const char *
                 p = TREE_STRING_POINTER(TREE_VALUE(TREE_PURPOSE(Input)));
             * p; ++p)
          if (*p == ',')
            ++NumInputChoices;
        if (NumChoices && (NumInputChoices != NumChoices)) {
          error("operand constraints for %<asm%> differ in number of "
                "alternatives");
          return;
        }
        if (NumChoices == 0)
          NumChoices = NumInputChoices;
      }
      for (unsigned i = 0; i != NumOutputs; ++i) {
        tree Output = gimple_asm_output_op(stmt, i);
        unsigned NumOutputChoices = 1;
        for (const char *
                 p = TREE_STRING_POINTER(TREE_VALUE(TREE_PURPOSE(Output)));
             * p; ++p)
          if (*p == ',')
            ++NumOutputChoices;
        if (NumChoices && (NumOutputChoices != NumChoices)) {
          error("operand constraints for %<asm%> differ in number of "
                "alternatives");
          return;
        }
        if (NumChoices == 0)
          NumChoices = NumOutputChoices;
      }

      // If there are multiple constraint tuples, pick one.  Constraints is
      // altered to point to shorter strings (which are malloc'ed), and everything
      // below Just Works as in the NumChoices==1 case.
      BumpPtrAllocator StringStorage;
      if (NumChoices > 1)
        ChooseConstraintTuple(stmt, Constraints, NumChoices, StringStorage);

      // HasSideEffects - Whether the LLVM inline asm should be marked as having
      // side effects.
      bool HasSideEffects = gimple_asm_volatile_p(stmt) || (NumOutputs == 0);

      // CallResultTypes - The inline asm call may return one or more results.  The
      // types of the results are recorded here along with a flag indicating whether
      // the corresponding GCC type is signed.
      SmallVector<std::pair<Type *, bool>, 4> CallResultTypes;

      // CallResultDests - Each result returned by the inline asm call is stored in
      // a memory location.  These are listed here along with a flag indicating if
      // the GCC type corresponding to the memory location is signed.  The type of
      // the memory location is allowed to differ from the type of the call result,
      // in which case the result is converted before being stored.
      SmallVector<std::pair<Value *, bool>, 4> CallResultDests;

      // CallOps - The operands pass to the inline asm call.
      SmallVector<Value *, 16> CallOps;

      // OutputLocations - For each output holds an index into CallOps (if the flag
      // is false) or into CallResultTypes (if the flag is true).  Outputs returned
      // in memory are passed to the asm as an operand and thus appear in CallOps.
      // Those returned in registers are obtained as one of the results of the asm
      // call and thus correspond to an entry in CallResultTypes.
      SmallVector<std::pair<bool, unsigned>, 4> OutputLocations;

      // SSADefinitions - If the asm defines an SSA name then the SSA name and a
      // memory location are recorded here.  The asm result defining the SSA name
      // will be stored to the memory memory location, and loaded out afterwards
      // to define the SSA name.
      SmallVector<std::pair<tree, MemRef>, 4> SSADefinitions;

      // ConstraintStr - The string of constraints in LLVM format.
      std::string ConstraintStr;

      // Process outputs.
      for (unsigned i = 0; i != NumOutputs; ++i) {
        tree Output = gimple_asm_output_op(stmt, i);
        tree Operand = TREE_VALUE(Output);

        // Parse the output constraint.
        const char *Constraint = Constraints[i];
        bool IsInOut, AllowsReg, AllowsMem;
        if (!parse_output_constraint(&Constraint, i, NumInputs, NumOutputs,
                                     &AllowsMem, &AllowsReg, &IsInOut))
          return;
        assert(Constraint[0] == '=' && "Not an output constraint?");
        assert(!IsInOut && "asm expression not gimplified?");

        std::string SimplifiedConstraint;
        // If this output register is pinned to a machine register, use that machine
        // register instead of the specified constraint.
        if (isa<VAR_DECL>(Operand) && DECL_HARD_REGISTER(Operand)) {
          const char *RegName = extractRegisterName(Operand);
          int RegNum = decode_reg_name(RegName);
          if (RegNum >= 0) {
            RegName = LLVM_GET_REG_NAME(RegName, RegNum);
            size_t RegNameLen = strlen(RegName);
            char *NewConstraint = (char *)alloca(RegNameLen + 3);
            NewConstraint[0] = '{';
            memcpy(NewConstraint + 1, RegName, RegNameLen);
            NewConstraint[RegNameLen + 1] = '}';
            NewConstraint[RegNameLen + 2] = 0;
            SimplifiedConstraint = NewConstraint;
            // This output will now be implicit; set the sideffect flag on the asm.
            HasSideEffects = true;
            // We should no longer consider mem constraints.
            AllowsMem = false;
          } else {
            // If we can simplify the constraint into something else, do so now.
            // This avoids LLVM having to know about all the (redundant) GCC
            // constraints.
            SimplifiedConstraint = CanonicalizeConstraint(Constraint + 1);
          }
        } else {
          SimplifiedConstraint = CanonicalizeConstraint(Constraint + 1);
        }

        LValue Dest;
        Type *DestValTy = ConvertType(TREE_TYPE(Operand));
        if (isa<SSA_NAME>(Operand)) {
          // The ASM is defining an ssa name.  Store the output to a temporary, then
          // load it out again later as the ssa name.
          MemRef TmpLoc = CreateTempLoc(DestValTy);
          SSADefinitions.push_back(std::make_pair(Operand, TmpLoc));
          Dest = LValue(TmpLoc);
        } else {
          Dest = EmitLV(Operand);
          assert(cast<PointerType>(Dest.Ptr->getType())->getElementType() ==
                 DestValTy && "LValue has wrong type!");
        }

        assert(!Dest.isBitfield() && "Cannot assign into a bitfield!");
        if (!AllowsMem &&
            DestValTy->isSingleValueType()) { // Reg dest -> asm return
          ConstraintStr += ",=";
          ConstraintStr += SimplifiedConstraint;
          bool IsSigned = !TYPE_UNSIGNED(TREE_TYPE(Operand));
          CallResultDests.push_back(std::make_pair(Dest.Ptr, IsSigned));
          CallResultTypes.push_back(std::make_pair(DestValTy, IsSigned));
          OutputLocations.push_back(
              std::make_pair(true, CallResultTypes.size() - 1));
        } else {
          ConstraintStr += ",=*";
          ConstraintStr += SimplifiedConstraint;
          CallOps.push_back(Dest.Ptr);
          OutputLocations.push_back(std::make_pair(false, CallOps.size() - 1));
        }
      }

      // Process inputs.
      for (unsigned i = 0; i != NumInputs; ++i) {
        tree Input = gimple_asm_input_op(stmt, i);
        tree Val = TREE_VALUE(Input);
        tree type = TREE_TYPE(Val);
        bool IsSigned = !TYPE_UNSIGNED(type);

        const char *Constraint = Constraints[NumOutputs + i];

        bool AllowsReg, AllowsMem;
        if (!parse_input_constraint(Constraints + NumOutputs + i, i, NumInputs,
                                    NumOutputs, 0, Constraints, &AllowsMem,
                                    &AllowsReg))
          return;
        bool isIndirect = false;
        if (AllowsReg || !AllowsMem) { // Register operand.
          Type *LLVMTy = ConvertType(type);

          Value *Op = 0;
          Type *OpTy = LLVMTy;
          if (LLVMTy->isSingleValueType()) {
            if (isa<ADDR_EXPR>(Val) && isa<LABEL_DECL>(TREE_OPERAND(Val, 0))) {
              // Emit the label, but do not assume it is going to be the target
              // of an indirect branch.  Having this logic here is a hack; there
              // should be a bit in the label identifying it as in an asm.
              Op = getLabelDeclBlock(TREE_OPERAND(Val, 0));
            } else if (isa<VAR_DECL>(Val) && DECL_HARD_REGISTER(Val)) {
              // GCC special cases hard registers used as inputs to asm statements.
              // Emit an inline asm node that copies the value out of the specified
              // register.
              assert(canEmitRegisterVariable(Val) &&
                     "Cannot read hard register!");
              Op = EmitReadOfRegisterVariable(Val);
            } else {
              Op = EmitMemory(Val);
            }
          } else {
            LValue LV = EmitLV(Val);
            assert(!LV.isBitfield() &&
                   "Inline asm can't have bitfield operand");

            // Small structs and unions can be treated as integers.
            uint64_t TySize = DL.getTypeSizeInBits(LLVMTy);
            if (TySize == 1 || TySize == 8 || TySize == 16 || TySize == 32 ||
                TySize == 64 || (TySize == 128 && !AllowsMem)) {
              LLVMTy = IntegerType::get(Context, (unsigned) TySize);
              Op = Builder.CreateLoad(
                  Builder.CreateBitCast(LV.Ptr, LLVMTy->getPointerTo()));
            } else {
              // Codegen only supports indirect operands with mem constraints.
              if (!AllowsMem)
                error(
                    "aggregate does not match inline asm register constraint");
              // Otherwise, emit our value as a lvalue.
              isIndirect = true;
              Op = LV.Ptr;
              OpTy = Op->getType();
            }
          }

          // If this input operand is matching an output operand, e.g. '0', check if
          // this is something that llvm supports. If the operand types are
          // different, then emit an error if 1) one of the types is not integer or
          // pointer, 2) if size of input type is larger than the output type. If
          // the size of the integer input size is smaller than the integer output
          // type, then cast it to the larger type and shift the value if the target
          // is big endian.
          if (ISDIGIT(Constraint[0])) {
            unsigned Match =
                (unsigned) atoi(Constraint); // Unsigned - no minus sign
            // This output might have gotten put in either CallResult or CallArg
            // depending whether it's a register or not.  Find its type.
            Type *OTy = 0;
            unsigned OutputIndex = ~0U;
            if (Match < OutputLocations.size()) {
              // Indices here known to be within range.
              OutputIndex = OutputLocations[Match].second;
              if (OutputLocations[Match].first)
                OTy = CallResultTypes[OutputIndex].first;
              else {
                OTy = CallOps[OutputIndex]->getType();
                assert(OTy->isPointerTy() && "Expected pointer type!");
                OTy = cast<PointerType>(OTy)->getElementType();
              }
            }
            if (OTy && OTy != OpTy) {
              if (!OTy->isSingleValueType() || !OpTy->isSingleValueType()) {
                error(
                    "unsupported inline asm: input constraint with a matching "
                    "output constraint of incompatible type!");
                return;
              }
              uint64_t OTyBits = DL.getTypeSizeInBits(OTy);
              uint64_t OpTyBits = DL.getTypeSizeInBits(OpTy);
              if (OTyBits == 0 || OpTyBits == 0) {
                error(
                    "unsupported inline asm: input constraint with a matching "
                    "output constraint of incompatible type!");
                return;
              } else if (OTyBits < OpTyBits) {
                // The output is smaller than the input.
                if (OutputLocations[Match].first &&
                    !isOperandMentioned(stmt, Match)) {
                  // The output is a register and is not explicitly mentioned in the
                  // asm string.  Use the input type for the output, and arrange for
                  // the result to be truncated to the original output type after
                  // the asm call.
                  CallResultTypes[OutputIndex] = std::make_pair(OpTy, IsSigned);
                } else if (isa<Constant>(Op) &&
                           !isOperandMentioned(stmt, NumOutputs + i)) {
                  // The input is a constant that is not explicitly mentioned in the
                  // asm string.  Convert to the output type like in an assignment.
                  Op = CastToAnyType(Op, IsSigned, OTy,
                                     CallResultTypes[OutputIndex].second);
                } else {
                  error("unsupported inline asm: input constraint with a "
                        "matching "
                        "output constraint of incompatible type!");
                  return;
                }
              } else if (OTyBits > OpTyBits) {
                // The input is smaller than the output.  If the input is explicitly
                // mentioned in the asm string then we cannot safely promote it, so
                // bail out.
                if (isOperandMentioned(stmt, NumOutputs + i)) {
                  error("unsupported inline asm: input constraint with a "
                        "matching "
                        "output constraint of incompatible type!");
                  return;
                }
                Op = CastToAnyType(Op, IsSigned, OTy,
                                   CallResultTypes[OutputIndex].second);
              }
            }
          }

          CallOps.push_back(Op);
        } else { // Memory operand.
          mark_addressable(TREE_VALUE(Input));
          isIndirect = true;
          LValue Src = EmitLV(Val);
          assert(!Src.isBitfield() && "Cannot read from a bitfield!");
          CallOps.push_back(Src.Ptr);
        }

        ConstraintStr += ',';
        if (isIndirect)
          ConstraintStr += '*';

        // If this input register is pinned to a machine register, use that machine
        // register instead of the specified constraint.
        if (isa<VAR_DECL>(Val) && DECL_HARD_REGISTER(Val)) {
          const char *RegName = extractRegisterName(Val);
          int RegNum = decode_reg_name(RegName);
          if (RegNum >= 0) {
            RegName = LLVM_GET_REG_NAME(RegName, RegNum);
            ConstraintStr += '{';
            ConstraintStr += RegName;
            ConstraintStr += '}';
            continue;
          }
        }

        // If there is a simpler form for the register constraint, use it.
        std::string Simplified = CanonicalizeConstraint(Constraint);
        ConstraintStr += Simplified;
      }

      // Process clobbers.

      // Some targets automatically clobber registers across an asm.
      tree Clobbers;
      {
        // Create input, output & clobber lists for the benefit of md_asm_clobbers.
        tree outputs = NULL_TREE;
        if (NumOutputs) {
          tree t = outputs = gimple_asm_output_op(stmt, 0);
          for (unsigned i = 1; i < NumOutputs; i++) {
            TREE_CHAIN(t) = gimple_asm_output_op(stmt, i);
            t = gimple_asm_output_op(stmt, i);
          }
        }

        tree inputs = NULL_TREE;
        if (NumInputs) {
          tree t = inputs = gimple_asm_input_op(stmt, 0);
          for (unsigned i = 1; i < NumInputs; i++) {
            TREE_CHAIN(t) = gimple_asm_input_op(stmt, i);
            t = gimple_asm_input_op(stmt, i);
          }
        }

        tree clobbers = NULL_TREE;
        if (NumClobbers) {
          tree t = clobbers = gimple_asm_clobber_op(stmt, 0);
          for (unsigned i = 1; i < NumClobbers; i++) {
            TREE_CHAIN(t) = gimple_asm_clobber_op(stmt, i);
            t = gimple_asm_clobber_op(stmt, i);
          }
        }

        Clobbers = targetm.md_asm_clobbers(outputs, inputs, clobbers);
      }

      for (; Clobbers; Clobbers = TREE_CHAIN(Clobbers)) {
        const char *RegName = TREE_STRING_POINTER(TREE_VALUE(Clobbers));
        int RegCode = decode_reg_name(RegName);

        switch (RegCode) {
        case -1: // Nothing specified?
        case -2: // Invalid.
          error("unknown register name %qs in %<asm%>", RegName);
          return;
        case -3: // cc
          ConstraintStr += ",~{cc}";
          break;
        case -4: // memory
          ConstraintStr += ",~{memory}";
          break;
        default : // Normal register name.
          assert(RegName && "Null register name successfully decoded!");
          RegName = LLVM_GET_REG_NAME(RegName, RegCode);
          ConstraintStr += ",~{";
          ConstraintStr += RegName;
          ConstraintStr += "}";
          break;
        }
      }

      // Compute the return type to use for the asm call.
      Type *CallResultType;
      switch (CallResultTypes.size()) {
        // If there are no results then the return type is void!
      case 0:
        CallResultType = Type::getVoidTy(Context);
        break;
        // If there is one result then use the result's type as the return type.
      case 1:
        CallResultType = CallResultTypes[0].first;
        break;
        // If the asm returns multiple results then create a struct type with the
        // result types as its fields, and use it for the return type.
      default:
        SmallVector<Type *, 4> Fields((unsigned) CallResultTypes.size());
        for (unsigned i = 0, e = (unsigned) CallResultTypes.size(); i != e; ++i)
          Fields[i] = CallResultTypes[i].first;
        CallResultType = StructType::get(Context, Fields);
        break;
      }

      // Compute the types of the arguments to the asm call.
      SmallVector<Type *, 16> CallArgTypes((unsigned) CallOps.size());
      for (unsigned i = 0, e = (unsigned) CallOps.size(); i != e; ++i)
        CallArgTypes[i] = CallOps[i]->getType();

      // Get the type of the called asm "function".
      FunctionType *FTy =
          FunctionType::get(CallResultType, CallArgTypes, false);

      // Remove the leading comma if we have operands.
      if (!ConstraintStr.empty())
        ConstraintStr.erase(ConstraintStr.begin());

      // Make sure we're created a valid inline asm expression.
      if (!InlineAsm::Verify(FTy, ConstraintStr)) {
        error("Invalid or unsupported inline assembly!");
        return;
      }

      std::string NewAsmStr = ConvertInlineAsmStr(stmt, NumOutputs + NumInputs);
      Value *Asm =
          InlineAsm::get(FTy, NewAsmStr, ConstraintStr, HasSideEffects);
      CallInst *CV = Builder.CreateCall(
          Asm, CallOps, CallResultTypes.empty() ? "" : "asmtmp");
      CV->setDoesNotThrow();
      if (gimple_has_location(stmt)) {
        // Pass the location of the asm using a !srcloc metadata.
        Constant *LocationCookie = Builder.getInt64(gimple_location(stmt));
        CV->setMetadata("srcloc", MDNode::get(Context, LocationCookie));
      }

      // If the call produces a value, store it into the destination.
      for (unsigned i = 0, NumResults = (unsigned) CallResultTypes.size();
           i != NumResults; ++i) {
        Value *Val =
            NumResults == 1 ? CV
                            : Builder.CreateExtractValue(CV, i, "asmresult");
        bool ValIsSigned = CallResultTypes[i].second;

        Value *Dest = CallResultDests[i].first;
        Type *DestTy = cast<PointerType>(Dest->getType())->getElementType();
        bool DestIsSigned = CallResultDests[i].second;
        Val = CastToAnyType(Val, ValIsSigned, DestTy, DestIsSigned);
        Builder.CreateStore(Val, Dest);
      }

      // If the call defined any ssa names, associate them with their value.
      for (unsigned i = 0, e = (unsigned) SSADefinitions.size(); i != e; ++i) {
        tree Name = SSADefinitions[i].first;
        MemRef Loc = SSADefinitions[i].second;
        Value *Val = LoadRegisterFromMemory(Loc, TREE_TYPE(Name), 0, Builder);
        DefineSSAName(Name, Val);
      }

      // Give the backend a chance to upgrade the inline asm to LLVM code.  This
      // handles some common cases that LLVM has intrinsics for, e.g. x86 bswap ->
      // llvm.bswap.
      if (const TargetLowering *TLI =
	  TheTarget->getSubtargetImpl()->getTargetLowering())
        TLI->ExpandInlineAsm(CV);
    }

    void TreeToLLVM::RenderGIMPLE_ASSIGN(gimple stmt) {
      tree lhs = gimple_assign_lhs(stmt);

#if (GCC_MINOR > 6)
      // Assigning a right-hand side with TREE_CLOBBER_P says that the left-hand
      // side is dead from this point on.  Output an llvm.lifetime.end intrinsic.
      if (get_gimple_rhs_class(gimple_expr_code(stmt)) == GIMPLE_SINGLE_RHS &&
          TREE_CLOBBER_P(gimple_assign_rhs1(stmt))) {
        // Be conservative and only output the intrinsic if the left-hand side
        // corresponds to some kind of concrete object.  Note that we generate
        // code to read from RESULT_DECLs before returning from the function, so
        // saying that a RESULT_DECL is dead means we are dead - which is why we
        // don't even consider it.
        if (isa<PARM_DECL>(lhs) || isa<VAR_DECL>(lhs)) {
          Value *LHSAddr =
              Builder.CreateBitCast(DECL_LOCAL(lhs), Builder.getInt8PtrTy());
          uint64_t LHSSize =
              isInt64(DECL_SIZE(lhs), true) ? getInt64(DECL_SIZE(lhs), true) / 8
                                            : ~0UL;
          Function *EndIntr =
              Intrinsic::getDeclaration(TheModule, Intrinsic::lifetime_end);
          Builder.CreateCall2(EndIntr, Builder.getInt64(LHSSize), LHSAddr);
        }
        return;
      }
#endif

      if (isa<AGGREGATE_TYPE>(TREE_TYPE(lhs))) {
        assert(get_gimple_rhs_class(gimple_expr_code(stmt)) ==
               GIMPLE_SINGLE_RHS && "Aggregate type but rhs not simple!");
        LValue LV = EmitLV(lhs);
        MemRef NewLoc(LV.Ptr, LV.getAlignment(), TREE_THIS_VOLATILE(lhs));
        EmitAggregate(gimple_assign_rhs1(stmt), NewLoc);
        return;
      }
      WriteScalarToLHS(lhs, EmitAssignRHS(stmt));
    }

    void TreeToLLVM::RenderGIMPLE_CALL(gimple stmt) {
      tree lhs = gimple_call_lhs(stmt);
      if (!lhs) {
        // The returned value is not used.
        if (!isa<AGGREGATE_TYPE>(gimple_call_return_type(stmt))) {
          OutputCallRHS(stmt, 0);
          return;
        }
        // Create a temporary to hold the returned value.
        // TODO: Figure out how to avoid creating this temporary and the
        // associated useless code that stores the returned value into it.
        MemRef Loc = CreateTempLoc(ConvertType(gimple_call_return_type(stmt)));
        OutputCallRHS(stmt, &Loc);
        return;
      }

      if (isa<AGGREGATE_TYPE>(TREE_TYPE(lhs))) {
        LValue LV = EmitLV(lhs);
        MemRef NewLoc(LV.Ptr, LV.getAlignment(), TREE_THIS_VOLATILE(lhs));
        OutputCallRHS(stmt, &NewLoc);
        return;
      }
      WriteScalarToLHS(lhs, OutputCallRHS(stmt, 0));
    }

    void TreeToLLVM::RenderGIMPLE_COND(gimple stmt) {
      // Emit the comparison.
      Value *Cond = EmitCompare(gimple_cond_lhs(stmt), gimple_cond_rhs(stmt),
                                gimple_cond_code(stmt));

      // Extract the target basic blocks.
      edge true_edge, false_edge;
      extract_true_false_edges_from_block(gimple_bb(stmt), &true_edge,
                                          &false_edge);
      BasicBlock *IfTrue = getBasicBlock(true_edge->dest);
      BasicBlock *IfFalse = getBasicBlock(false_edge->dest);

      // Branch based on the condition.
      Builder.CreateCondBr(Cond, IfTrue, IfFalse);
    }

    void TreeToLLVM::RenderGIMPLE_EH_DISPATCH(gimple stmt) {
      int RegionNo = gimple_eh_dispatch_region(stmt);
      eh_region region = get_eh_region_from_number(RegionNo);

      switch (region->type) {
      default:
        llvm_unreachable("Unexpected region type!");
      case ERT_ALLOWED_EXCEPTIONS: {
        // Filter.
        BasicBlock *Dest = getLabelDeclBlock(region->u.allowed.label);

        if (!region->u.allowed.type_list) {
          // Not allowed to throw.  Branch directly to the post landing pad.
          Builder.CreateBr(Dest);
          BeginBlock(BasicBlock::Create(Context));
          break;
        }

        // The result of a filter selection will be a negative index if there is a
        // match.
        // FIXME: It looks like you have to compare against a specific value,
        // checking for any old negative number is not enough!  This should not
        // matter if the failure code branched to on a filter match is always the
        // same (as in C++), but might cause problems with other languages.
        Value *Filter = Builder.CreateLoad(getExceptionFilter(RegionNo));

        // Compare with the filter action value.
        Value *Zero = ConstantInt::get(Filter->getType(), 0);
        Value *Compare = Builder.CreateICmpSLT(Filter, Zero);

        // Branch on the compare.
        BasicBlock *NoMatchBB = BasicBlock::Create(Context);
        Builder.CreateCondBr(Compare, Dest, NoMatchBB);
        BeginBlock(NoMatchBB);
        break;
      }
      case ERT_TRY:
        // Catches.
        Value *Filter = NULL;
        SmallSet<Value *, 8> AlreadyCaught; // Typeinfos known caught.
        Function *TypeIDIntr =
            Intrinsic::getDeclaration(TheModule, Intrinsic::eh_typeid_for);
        for (eh_catch c = region->u.eh_try.first_catch; c; c = c->next_catch) {
          BasicBlock *Dest = getLabelDeclBlock(c->label);
          if (!c->type_list) {
            // Catch-all.  Branch directly to the post landing pad.
            Builder.CreateBr(Dest);
            break;
          }

          Value *Cond = NULL;
          for (tree type = c->type_list; type; type = TREE_CHAIN(type)) {
            Value *TypeInfo = ConvertTypeInfo(TREE_VALUE(type));
            // No point in trying to catch a typeinfo that was already caught.
            if (!AlreadyCaught.insert(TypeInfo).second)
              continue;

            TypeInfo = Builder.CreateBitCast(TypeInfo, Builder.getInt8PtrTy());

            // Call get eh type id.
            Value *TypeID = Builder.CreateCall(TypeIDIntr, TypeInfo, "typeid");

            if (!Filter)
              Filter = Builder.CreateLoad(getExceptionFilter(RegionNo));

            // Compare with the exception selector.
            Value *Compare = Builder.CreateICmpEQ(Filter, TypeID);

            Cond = Cond ? Builder.CreateOr(Cond, Compare) : Compare;
          }

          if (Cond) {
            BasicBlock *NoMatchBB = BasicBlock::Create(Context);
            Builder.CreateCondBr(Cond, Dest, NoMatchBB);
            BeginBlock(NoMatchBB);
          }
        }
        break;
      }
    }

    void TreeToLLVM::RenderGIMPLE_GOTO(gimple stmt) {
      tree dest = gimple_goto_dest(stmt);

      if (isa<LABEL_DECL>(dest)) {
        // Direct branch.
        Builder.CreateBr(getLabelDeclBlock(dest));
        return;
      }

      // Indirect branch.
      basic_block source = gimple_bb(stmt);
      IndirectBrInst *Br = Builder.CreateIndirectBr(EmitRegister(dest),
                                                    EDGE_COUNT(source->succs));

      // Add the list of possible destinations.
      edge e;
      edge_iterator ei;
      FOR_EACH_EDGE(e, ei, source->succs)
          Br->addDestination(getBasicBlock(e->dest));
    }

    void TreeToLLVM::RenderGIMPLE_RESX(gimple stmt) {
      // Reraise an exception.  If this statement is inside an exception handling
      // region then the reraised exception may be caught by the current function,
      // in which case it can be simplified into a branch.
      int DstLPadNo = lookup_stmt_eh_lp(stmt);
      eh_region dst_rgn =
          DstLPadNo ? get_eh_region_from_lp_number(DstLPadNo) : NULL;
      eh_region src_rgn = get_eh_region_from_number(gimple_resx_region(stmt));

      if (!src_rgn) {
        // Unreachable block?
        Builder.CreateUnreachable();
        return;
      }

      if (dst_rgn) {
        if (DstLPadNo < 0) {
          // The reraise is inside a must-not-throw region.  Turn the reraise into a
          // call to the failure routine (eg: std::terminate).
          assert(dst_rgn->type == ERT_MUST_NOT_THROW &&
                 "Unexpected region type!");

          // Branch to the block containing the failure code.
          Builder.CreateBr(getFailureBlock(dst_rgn->index));
          return;
        }

        // Use the exception pointer and filter value for the source region as the
        // values for the destination region.
        Value *ExcPtr = Builder.CreateLoad(getExceptionPtr(src_rgn->index));
        Builder.CreateStore(ExcPtr, getExceptionPtr(dst_rgn->index));
        Value *Filter = Builder.CreateLoad(getExceptionFilter(src_rgn->index));
        Builder.CreateStore(Filter, getExceptionFilter(dst_rgn->index));

        // Branch to the post landing pad for the destination region.
        eh_landing_pad lp = get_eh_landing_pad_from_number(DstLPadNo);
        assert(lp && "Post landing pad not found!");
        Builder.CreateBr(getLabelDeclBlock(lp->post_landing_pad));
        return;
      }

      // Unwind the exception out of the function using a resume instruction.
      Value *ExcPtr = Builder.CreateLoad(getExceptionPtr(src_rgn->index));
      Value *Filter = Builder.CreateLoad(getExceptionFilter(src_rgn->index));
      Type *UnwindDataTy =
          StructType::get(Builder.getInt8PtrTy(), Builder.getInt32Ty(), NULL);
      Value *UnwindData = UndefValue::get(UnwindDataTy);
      UnwindData = Builder.CreateInsertValue(UnwindData, ExcPtr, 0, "exc_ptr");
      UnwindData = Builder.CreateInsertValue(UnwindData, Filter, 1, "filter");
      Builder.CreateResume(UnwindData);
    }

    void TreeToLLVM::RenderGIMPLE_RETURN(gimple stmt) {
      tree retval = gimple_return_retval(stmt);
      tree result = DECL_RESULT(current_function_decl);

      if (retval && retval != error_mark_node && retval != result) {
        // Store the return value to the function's DECL_RESULT.
        MemRef DestLoc(DECL_LOCAL(result), 1, false); // FIXME: What alignment?
        if (isa<AGGREGATE_TYPE>(TREE_TYPE(result))) {
          EmitAggregate(retval, DestLoc);
        } else {
          Value *Val = Builder.CreateBitCast(EmitRegister(retval),
                                             getRegType(TREE_TYPE(result)));
          StoreRegisterToMemory(Val, DestLoc, TREE_TYPE(result), 0, Builder);
        }
      }

      // Emit a branch to the exit label.
      if (!ReturnBB)
        // Create a new block for the return node, but don't insert it yet.
        ReturnBB = BasicBlock::Create(Context, "return");

      Builder.CreateBr(ReturnBB);
    }

    void TreeToLLVM::RenderGIMPLE_SWITCH(gimple stmt) {
      // Emit the condition.
      Value *Index = EmitRegister(gimple_switch_index(stmt));
      tree index_type = TREE_TYPE(gimple_switch_index(stmt));

      // Create the switch instruction.
      tree default_label = CASE_LABEL(gimple_switch_label(stmt, 0));
      SwitchInst *SI =
          Builder.CreateSwitch(Index, getLabelDeclBlock(default_label),
                               gimple_switch_num_labels(stmt));

      // Add the switch cases.
      BasicBlock *IfBlock = 0; // Set if a range was output as an "if".
      for (unsigned i = 1, e = gimple_switch_num_labels(stmt); i != e; ++i) {
        tree label = gimple_switch_label(stmt, i);
        BasicBlock *Dest = getLabelDeclBlock(CASE_LABEL(label));

        // Convert the integer to the right type.
        Value *Val = EmitRegisterWithCast(CASE_LOW(label), index_type);
        ConstantInt *LowC = cast<ConstantInt>(Val);

        if (!CASE_HIGH(label)) {
          SI->addCase(LowC, Dest); // Single destination.
          continue;
        }

        // Otherwise, we have a range, like 'case 1 ... 17'.
        // Make sure the case value is the same type as the switch expression
        Val = EmitRegisterWithCast(CASE_HIGH(label), index_type);
        ConstantInt *HighC = cast<ConstantInt>(Val);

        APInt Range = HighC->getValue() - LowC->getValue();
        if (Range.ult(APInt(Range.getBitWidth(), 64))) {
          // Add all of the necessary successors to the switch.
          APInt CurrentValue = LowC->getValue();
          while (1) {
            SI->addCase(LowC, Dest);
            if (LowC == HighC)
              break; // Emitted the last one.
            CurrentValue++;
            LowC = ConstantInt::get(Context, CurrentValue);
          }
        } else {
          // The range is too big to add to the switch - emit an "if".
          if (!IfBlock) {
            IfBlock = BasicBlock::Create(Context);
            BeginBlock(IfBlock);
          }
          Value *Diff = Builder.CreateSub(Index, LowC);
          Value *Cond =
              Builder.CreateICmpULE(Diff, ConstantInt::get(Context, Range));
          BasicBlock *False_Block = BasicBlock::Create(Context);
          Builder.CreateCondBr(Cond, Dest, False_Block);
          BeginBlock(False_Block);
        }
      }

      if (IfBlock) {
        Builder.CreateBr(SI->getDefaultDest());
        SI->setDefaultDest(IfBlock);
      }
    }

    //===----------------------------------------------------------------------===//
    //                          ... Render helpers ...
    //===----------------------------------------------------------------------===//

    /// EmitAssignRHS - Convert the RHS of a scalar GIMPLE_ASSIGN to LLVM.
    Value *TreeToLLVM::EmitAssignRHS(gimple stmt) {
      // Loads from memory and other non-register expressions are handled by
      // EmitAssignSingleRHS.
      if (get_gimple_rhs_class(gimple_expr_code(stmt)) == GIMPLE_SINGLE_RHS) {
        Value *RHS = EmitAssignSingleRHS(gimple_assign_rhs1(stmt));
        assert(RHS->getType() ==
               getRegType(TREE_TYPE(gimple_assign_rhs1(stmt))) &&
               "RHS has wrong type!");
        return RHS;
      }

      // The RHS is a register expression.  Emit it now.
      tree type = TREE_TYPE(gimple_assign_lhs(stmt));
      tree_code code = gimple_assign_rhs_code(stmt);
      tree rhs1 = gimple_assign_rhs1(stmt);
      tree rhs2 = gimple_assign_rhs2(stmt);
#if (GCC_MINOR > 5)
      tree rhs3 = gimple_assign_rhs3(stmt);
#endif

      Value *RHS = 0;
      switch (code) {
      default:
        debug_gimple_stmt(stmt);
        llvm_unreachable("Unsupported GIMPLE assignment!");

        // Unary expressions.
      case ABS_EXPR:
        RHS = EmitReg_ABS_EXPR(rhs1);
        break;
      case BIT_NOT_EXPR:
        RHS = EmitReg_BIT_NOT_EXPR(rhs1);
        break;
      case CONJ_EXPR:
        RHS = EmitReg_CONJ_EXPR(rhs1);
        break;
      case CONVERT_EXPR:
      case FIX_TRUNC_EXPR:
      case FLOAT_EXPR:
      case NOP_EXPR:
        RHS = EmitReg_CONVERT_EXPR(type, rhs1);
        break;
      case NEGATE_EXPR:
        RHS = EmitReg_NEGATE_EXPR(rhs1);
        break;
      case PAREN_EXPR:
        RHS = EmitReg_PAREN_EXPR(rhs1);
        break;
      case TRUTH_NOT_EXPR:
        RHS = EmitReg_TRUTH_NOT_EXPR(type, rhs1);
        break;

        // Comparisons.
      case EQ_EXPR:
      case GE_EXPR:
      case GT_EXPR:
      case LE_EXPR:
      case LT_EXPR:
      case LTGT_EXPR:
      case NE_EXPR:
      case ORDERED_EXPR:
      case UNEQ_EXPR:
      case UNGE_EXPR:
      case UNGT_EXPR:
      case UNLE_EXPR:
      case UNLT_EXPR:
      case UNORDERED_EXPR:
        // The GCC result may be of any integer type.
        RHS =
            Builder.CreateZExt(EmitCompare(rhs1, rhs2, code), getRegType(type));
        break;

        // Binary expressions.
      case BIT_AND_EXPR:
        RHS = EmitReg_BIT_AND_EXPR(rhs1, rhs2);
        break;
      case BIT_IOR_EXPR:
        RHS = EmitReg_BIT_IOR_EXPR(rhs1, rhs2);
        break;
      case BIT_XOR_EXPR:
        RHS = EmitReg_BIT_XOR_EXPR(rhs1, rhs2);
        break;
      case CEIL_DIV_EXPR:
        RHS = EmitReg_CEIL_DIV_EXPR(rhs1, rhs2);
        break;
      case COMPLEX_EXPR:
        RHS = EmitReg_COMPLEX_EXPR(rhs1, rhs2);
        break;
      case EXACT_DIV_EXPR:
        RHS = EmitReg_TRUNC_DIV_EXPR(rhs1, rhs2, /*isExact*/ true);
        break;
      case FLOOR_DIV_EXPR:
        RHS = EmitReg_FLOOR_DIV_EXPR(rhs1, rhs2);
        break;
      case FLOOR_MOD_EXPR:
        RHS = EmitReg_FLOOR_MOD_EXPR(rhs1, rhs2);
        break;
      case LROTATE_EXPR:
        RHS = EmitReg_RotateOp(type, rhs1, rhs2, Instruction::Shl,
                               Instruction::LShr);
        break;
      case LSHIFT_EXPR:
        RHS = EmitReg_ShiftOp(rhs1, rhs2, Instruction::Shl);
        break;
      case MAX_EXPR:
        RHS = EmitReg_MinMaxExpr(rhs1, rhs2, ICmpInst::ICMP_UGE,
                                 ICmpInst::ICMP_SGE, FCmpInst::FCMP_OGE);
        break;
      case MIN_EXPR:
        RHS = EmitReg_MinMaxExpr(rhs1, rhs2, ICmpInst::ICMP_ULE,
                                 ICmpInst::ICMP_SLE, FCmpInst::FCMP_OLE);
        break;
      case MINUS_EXPR:
        RHS = EmitReg_MINUS_EXPR(rhs1, rhs2);
        break;
      case MULT_EXPR:
        RHS = EmitReg_MULT_EXPR(rhs1, rhs2);
        break;
      case PLUS_EXPR:
        RHS = EmitReg_PLUS_EXPR(rhs1, rhs2);
        break;
      case POINTER_PLUS_EXPR:
        RHS = EmitReg_POINTER_PLUS_EXPR(rhs1, rhs2);
        break;
      case RDIV_EXPR:
        RHS = EmitReg_RDIV_EXPR(rhs1, rhs2);
        break;
      case REDUC_MAX_EXPR:
        RHS = EmitReg_ReducMinMaxExpr(rhs1, ICmpInst::ICMP_UGE,
                                      ICmpInst::ICMP_SGE, FCmpInst::FCMP_OGE);
        break;
      case REDUC_MIN_EXPR:
        RHS = EmitReg_ReducMinMaxExpr(rhs1, ICmpInst::ICMP_ULE,
                                      ICmpInst::ICMP_SLE, FCmpInst::FCMP_OLE);
        break;
      case REDUC_PLUS_EXPR:
        RHS = EmitReg_REDUC_PLUS_EXPR(rhs1);
        break;
      case ROUND_DIV_EXPR:
        RHS = EmitReg_ROUND_DIV_EXPR(rhs1, rhs2);
        break;
      case RROTATE_EXPR:
        RHS = EmitReg_RotateOp(type, rhs1, rhs2, Instruction::LShr,
                               Instruction::Shl);
        break;
      case RSHIFT_EXPR:
        RHS = EmitReg_ShiftOp(rhs1, rhs2,
                              TYPE_UNSIGNED(type) ? Instruction::LShr
                                                  : Instruction::AShr);
        break;
      case TRUNC_DIV_EXPR:
        RHS = EmitReg_TRUNC_DIV_EXPR(rhs1, rhs2, /*isExact*/ false);
        break;
      case TRUNC_MOD_EXPR:
        RHS = EmitReg_TRUNC_MOD_EXPR(rhs1, rhs2);
        break;
      case TRUTH_AND_EXPR:
        RHS = EmitReg_TruthOp(type, rhs1, rhs2, Instruction::And);
        break;
      case TRUTH_OR_EXPR:
        RHS = EmitReg_TruthOp(type, rhs1, rhs2, Instruction::Or);
        break;
      case TRUTH_XOR_EXPR:
        RHS = EmitReg_TruthOp(type, rhs1, rhs2, Instruction::Xor);
        break;
#if (GCC_MINOR < 7)
      case VEC_EXTRACT_EVEN_EXPR:
        RHS = EmitReg_VEC_EXTRACT_EVEN_EXPR(rhs1, rhs2);
        break;
      case VEC_EXTRACT_ODD_EXPR:
        RHS = EmitReg_VEC_EXTRACT_ODD_EXPR(rhs1, rhs2);
        break;
      case VEC_INTERLEAVE_HIGH_EXPR:
        RHS = EmitReg_VEC_INTERLEAVE_HIGH_EXPR(rhs1, rhs2);
        break;
      case VEC_INTERLEAVE_LOW_EXPR:
        RHS = EmitReg_VEC_INTERLEAVE_LOW_EXPR(rhs1, rhs2);
        break;
#endif
      case VEC_LSHIFT_EXPR:
        RHS = EmitReg_VecShiftOp(rhs1, rhs2, /*isLeftShift*/ true);
        break;
      case VEC_PACK_FIX_TRUNC_EXPR:
      case VEC_PACK_TRUNC_EXPR:
        RHS = EmitReg_VEC_PACK_TRUNC_EXPR(type, rhs1, rhs2);
        break;
      case VEC_RSHIFT_EXPR:
        RHS = EmitReg_VecShiftOp(rhs1, rhs2, /*isLeftShift*/ false);
        break;
      case VEC_UNPACK_FLOAT_HI_EXPR:
      case VEC_UNPACK_HI_EXPR:
        RHS = EmitReg_VecUnpackHiExpr(type, rhs1);
        break;
      case VEC_UNPACK_FLOAT_LO_EXPR:
      case VEC_UNPACK_LO_EXPR:
        RHS = EmitReg_VecUnpackLoExpr(type, rhs1);
        break;
      case VEC_WIDEN_MULT_HI_EXPR:
        RHS = EmitReg_VEC_WIDEN_MULT_HI_EXPR(type, rhs1, rhs2);
        break;
      case VEC_WIDEN_MULT_LO_EXPR:
        RHS = EmitReg_VEC_WIDEN_MULT_LO_EXPR(type, rhs1, rhs2);
        break;
      case WIDEN_MULT_EXPR:
        RHS = EmitReg_WIDEN_MULT_EXPR(type, rhs1, rhs2);
        break;

// Ternary expressions.
#if (GCC_MINOR > 5)
      case FMA_EXPR:
        RHS = EmitReg_FMA_EXPR(rhs1, rhs2, rhs3);
        break;
#endif
#if (GCC_MINOR > 6)
      case COND_EXPR:
      case VEC_COND_EXPR:
        RHS = EmitReg_CondExpr(rhs1, rhs2, rhs3);
        break;
      case VEC_PERM_EXPR:
        RHS = EmitReg_VEC_PERM_EXPR(rhs1, rhs2, rhs3);
        break;
#endif
      }

      return TriviallyTypeConvert(RHS, getRegType(type));
    }

    /// EmitAssignSingleRHS - Helper for EmitAssignRHS.  Handles those RHS that are
    /// not register expressions.
    Value *TreeToLLVM::EmitAssignSingleRHS(tree rhs) {
      assert(!isa<AGGREGATE_TYPE>(TREE_TYPE(rhs)) && "Expected a scalar type!");

      switch (TREE_CODE(rhs)) {
        // Catch-all for SSA names, constants etc.
      default:
        return EmitRegister(rhs);

        // Expressions (tcc_expression).
      case ADDR_EXPR:
        return EmitADDR_EXPR(rhs);
#if (GCC_MINOR < 7)
      case COND_EXPR:
      case VEC_COND_EXPR:
        return EmitCondExpr(rhs);
#endif
      case OBJ_TYPE_REF:
        return EmitOBJ_TYPE_REF(rhs);

        // Exceptional (tcc_exceptional).
      case CONSTRUCTOR:
        // Vector constant constructors are gimple invariant.
        return is_gimple_constant(rhs) ? EmitRegisterConstant(rhs)
                                       : EmitCONSTRUCTOR(rhs, 0);

        // References (tcc_reference).
      case ARRAY_REF:
      case ARRAY_RANGE_REF:
      case BIT_FIELD_REF:
      case COMPONENT_REF:
      case IMAGPART_EXPR:
      case INDIRECT_REF:
#if (GCC_MINOR > 5)
      case MEM_REF:
#endif
#if (GCC_MINOR < 6)
      case MISALIGNED_INDIRECT_REF:
#endif
      case REALPART_EXPR:
      case TARGET_MEM_REF:
      case VIEW_CONVERT_EXPR:
        return EmitLoadOfLValue(rhs); // Load from memory.

        // Declarations (tcc_declaration).
      case PARM_DECL:
      case RESULT_DECL:
      case VAR_DECL:
        return EmitLoadOfLValue(rhs); // Load from memory.

        // Constants (tcc_constant).
      case STRING_CST:
        return EmitLoadOfLValue(rhs); // Load from memory.
      }
    }

    /// OutputCallRHS - Convert the RHS of a GIMPLE_CALL.
    Value *TreeToLLVM::OutputCallRHS(gimple stmt, const MemRef * DestLoc) {
      // Check for a built-in function call.  If we can lower it directly, do so
      // now.
      tree fndecl = gimple_call_fndecl(stmt);
      if (fndecl && DECL_BUILT_IN(fndecl) &&
          DECL_BUILT_IN_CLASS(fndecl) != BUILT_IN_FRONTEND) {
        Value *Res = 0;
        if (EmitBuiltinCall(stmt, fndecl, DestLoc, Res))
          return Res ? Mem2Reg(Res, gimple_call_return_type(stmt), Builder) : 0;
      }

      tree call_expr = gimple_call_fn(stmt);
      assert(TREE_TYPE(call_expr) &&
             (isa<POINTER_TYPE>(TREE_TYPE(call_expr)) ||
              isa<REFERENCE_TYPE>(TREE_TYPE(call_expr))) &&
             "Not calling a function pointer?");

#if (GCC_MINOR < 7)
      tree function_type = TREE_TYPE(TREE_TYPE(call_expr));
#else
      tree function_type = gimple_call_fntype(stmt);
#endif
      Value *Callee = EmitRegister(call_expr);
      CallingConv::ID CallingConv;
      AttributeSet PAL;

      Type *Ty;
      // If this is a K&R-style function: with a type that takes no arguments but
      // with arguments none the less, then calculate the LLVM type from the list
      // of arguments.
      if (flag_functions_from_args) {
        tree *FirstArgAddr =
            gimple_call_num_args(stmt) > 0 ? gimple_call_arg_ptr(stmt, 0)
                                           : NULL;
        Ty = ConvertArgListToFnType(
            function_type,
            ArrayRef<tree>(FirstArgAddr, gimple_call_num_args(stmt)),
            gimple_call_chain(stmt), !flag_functions_from_args, CallingConv,
            PAL);
      } else {
        Ty = ConvertFunctionType(function_type, fndecl, gimple_call_chain(stmt),
                                 CallingConv, PAL);
      }

      // If this is a direct call to a function using a static chain then we need
      // to ensure the function type is the one just calculated: it has an extra
      // parameter for the chain.
      Callee = Builder.CreateBitCast(Callee, Ty->getPointerTo());

      Value *Result = EmitCallOf(Callee, stmt, DestLoc, PAL);

      // When calling a "noreturn" function output an unreachable instruction right
      // after the function to prevent LLVM from thinking that control flow will
      // fall into the subsequent block.
      if (gimple_call_flags(stmt) & ECF_NORETURN) {
        Builder.CreateUnreachable();
        BeginBlock(BasicBlock::Create(Context));
      }

      return Result ? Mem2Reg(Result, gimple_call_return_type(stmt), Builder)
                    : 0;
    }

/// WriteScalarToLHS - Store RHS, a non-aggregate value, into the given LHS.
void TreeToLLVM::WriteScalarToLHS(tree lhs, Value * RHS) {
  tree type = TREE_TYPE(lhs);

  // May need a useless type conversion (useless_type_conversion_p).
  RHS = TriviallyTypeConvert(RHS, getRegType(type));

  // If this is the definition of an ssa name, record it in the SSANames map.
  if (isa<SSA_NAME>(lhs)) {
    if (flag_verbose_asm)
      NameValue(RHS, lhs);
    DefineSSAName(lhs, RHS);
    return;
  }

  if (canEmitRegisterVariable(lhs)) {
    // If this is a store to a register variable, EmitLV can't handle the dest
    // (there is no l-value of a register variable).  Emit an inline asm node
    // that copies the value into the specified register.
    EmitModifyOfRegisterVariable(lhs, RHS);
    return;
  }

  LValue LV = EmitLV(lhs);
  LV.Volatile = TREE_THIS_VOLATILE(lhs);
  // TODO: Arrange for Volatile to already be set in the LValue.
  if (!LV.isBitfield()) {
    // Non-bitfield, scalar value.  Just emit a store.
    StoreRegisterToMemory(RHS, LV, type, describeAliasSet(lhs), Builder);
    return;
  }

  // Last case, this is a store to a bitfield, so we have to emit a
  // read/modify/write sequence.
  if (!LV.BitSize)
    return;

  // Load and store the minimum number of bytes that covers the field.
  unsigned LoadSizeInBits = LV.BitStart + LV.BitSize;
  LoadSizeInBits =
      (unsigned) RoundUpToAlignment(LoadSizeInBits, BITS_PER_UNIT);
  Type *LoadType = IntegerType::get(Context, LoadSizeInBits);

  // Load the existing bits.
  Value *Ptr = Builder.CreateBitCast(LV.Ptr, LoadType->getPointerTo());
  Value *Val =
      Builder.CreateAlignedLoad(Ptr, LV.getAlignment(), LV.Volatile);

  // Turn RHS into a bunch of bits by storing it to a temporary then loading it
  // out again as an integer.  The temporary needs to be big enough to hold the
  // in-memory representation of RHS.  If the bitfield is wider than this (which
  // only happens for non C-like languages) then any extra bits are undefined.
  // We tell the optimizers that they are undefined by widening the temporary to
  // at least the bitfield size but not storing anything to the extra bits.
  unsigned MemSize = GET_MODE_BITSIZE(TYPE_MODE(type));
  unsigned TmpSize = std::max(LoadSizeInBits, MemSize);
  Type *TmpType = IntegerType::get(Context, TmpSize);

  // Create the temporary, an integer.  Ensure it is aligned enough for both RHS
  // and the integer version of RHS.
  unsigned Alignment = std::max(TYPE_ALIGN(type) / 8,
                                DL.getPrefTypeAlignment(TmpType));
  Value *Tmp = CreateTemporary(TmpType, Alignment);

  // Store the right-hand side to it.  Ensure that any extra bits turn up in the
  // high bits of the integer loaded out below.
  MemRef TmpLoc(Tmp, Alignment, false);
  if (BYTES_BIG_ENDIAN && MemSize < LoadSizeInBits) {
    unsigned BitOffset = LoadSizeInBits - MemSize;
    assert(BitOffset % BITS_PER_UNIT == 0 && "Mode size not round?");
    TmpLoc = DisplaceLocationByUnits(TmpLoc, BitOffset/BITS_PER_UNIT, Builder);
  }
  StoreRegisterToMemory(RHS, TmpLoc, type, 0, Builder);

  // Load it out again as an integer.  Only the first LV.BitSize bits of this
  // integer will be used (see the masking below).  For C-like languages, the
  // original RHS is always an integer that is at least as wide as LV.BitSize,
  // so the used bits are just the original integer truncated to be LV.BitSize
  // bits wide.
  RHS = Builder.CreateIntCast(Builder.CreateLoad(Tmp), LoadType,
                              !TYPE_UNSIGNED(type));

  // Shift the right-hand side so that its bits are in the right position.
  unsigned FirstBitInVal =
      BYTES_BIG_ENDIAN ? LoadSizeInBits - LV.BitStart - LV.BitSize
                       : LV.BitStart;
  if (FirstBitInVal) {
    Value *ShAmt = ConstantInt::get(LoadType, FirstBitInVal);
    RHS = Builder.CreateShl(RHS, ShAmt);
  }
  // Mask out any bits in the right-hand side that shouldn't be in the result.
  // The lower bits are zero already, so this only changes bits off the end.
  APInt Mask = APInt::getBitsSet(LoadSizeInBits, FirstBitInVal,
                                 FirstBitInVal + LV.BitSize);
  if (FirstBitInVal + LV.BitSize != LoadSizeInBits)
    RHS = Builder.CreateAnd(RHS, ConstantInt::get(Context, Mask));

  // Mask out those bits in the original value that are being replaced by the
  // right-hand side.
  Val = Builder.CreateAnd(Val, ConstantInt::get(Context, ~Mask));

  // Finally, merge the two together and store it.
  Val = Builder.CreateOr(Val, RHS);
  Builder.CreateAlignedStore(Val, Ptr, LV.getAlignment(), LV.Volatile);
}
